LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Blogs > TheIndependentAquarius
User Name
Password

Notices

Rate this Entry

What is: Abstract base class, and Pure Virtual function - C++

Posted 11-21-2011 at 04:42 AM by TheIndependentAquarius
Updated 01-10-2012 at 08:17 AM by TheIndependentAquarius

  • In the cases where the derived classes may share the common functionality
    but with altogether "different" definitions, it makes sense to force the
    developers to create their own definitions for those common functions in
    concerned derived classes.
    This can be achieved by making the class "abstract".
  • A class is called an "abstract" class when it contains at least one "pure
    virtual
    " function.
  • A "pure virtual" function is a function which stops the object creation of a
    class.

    By placing a "pure virtual" function in a class, you tell the compiler to reserve
    a slot for a function in the "virtual table", but not to put any address in that
    particular slot.
    Even if only one function in a class is declared as "pure virtual", the "virtual
    table
    " is incomplete.
    If the "virtual table" for a class is incomplete, the compiler cannot allow the
    creation of an object of that class, so we get an error message from the
    compiler (on trying to create an object of an abstract class).

    Code:
    #include <iostream>
    using namespace std;
    
    class humanIdentification
    {
    	public:
                    // The way to make a virtual function pure virtual is to attach "= 0" at the end of its declaration.
    		virtual void fingerPrint () = 0;
    };
    
    int main ()
    {
    	humanIdentification objHumanIdentification;
    	return 0;
    }
    Output:
    Code:
    anisha@linux-dopx:~> g++ x.cpp
    x.cpp: In function ‘int main()’:
    x.cpp:12:13: error: cannot declare variable ‘objHumanIdentification’ to be of abstract type ‘humanIdentification’
    x.cpp:5:1: note:   because the following virtual functions are pure within ‘humanIdentification’:
    x.cpp:7:17: note: 	virtual void humanIdentification::fingerPrint()
  • "Pure virtual" functions CAN have "definitions" in the "base" class.
    Code:
    #include <iostream>
    using namespace std;
    
    class speciesFamily
    {
        public:
            virtual void numberOfLegs () = 0;
    };
    
    // Defining the pure virtual function in the abstract base class itself.
    void speciesFamily :: numberOfLegs ()
    {
        cout << "\nFour";
    }
    
    class catFamily : public speciesFamily
    {
        public:
            void numberOfLegs ()
            {
                // Calling the abstract base class's pure virtual function from the derived class.
                speciesFamily :: numberOfLegs ();
            }
    };
    
    int main ()
    {
    	catFamily objCat;
    	objCat.numberOfLegs ();
    
            return 0;
    }
    Output:
    Code:
    anisha@linux-dopx:~/Desktop> g++ x1.cpp
    anisha@linux-dopx:~/Desktop> ./a.out
    
    Four
  • Also, there can be a case where a class contains only the functions which are supposed
    to be used for the internal calculations (something which the end user will never need to
    see directly). In this case too one way of stopping the end user from creating its objects,
    is to make it abstract.

    In the above case, in order to avoid reimplementing a useless dummy pure virtual function
    again in the derived classes, one can define a "pure virtual destructor" in the abstract base
    class.
  • It is compulsory for a "pure virtual destructor" to have a definition in the concerned class itself.
    Code:
    class A
    {
    	public:
                    // The pure virtual destructor.
    		virtual ~A() = 0;
    };
    
    // No definition of the above declared pure virtual destructor.
    
    class B : public A
    {
    };
    
    int main ()
    {
    	B b;
    	return 0;
    }
    Output:
    Code:
    anisha@linux-dopx:~> g++ x1.cpp
    /tmp/ccrMg8PG.o: In function `B::~B()':
    x1.cpp:(.text._ZN1BD2Ev[_ZN1BD5Ev]+0x1f): undefined reference to `A::~A()'
    collect2: ld returned 1 exit status
  • "Pure virtual" functions can NOT be defined "inline".
    Code:
    #include <iostream>
    using namespace std;
    
    class A
    {
    	public:
    		// Inline definition of a pure virtual function
    		virtual void A1 () = 0 
    		{
    		}
    };
    
    int main ()
    {
    	return 0;
    }
    Output:
    Code:
    anisha@linux-dopx:~> g++ x.cpp
    x.cpp:7:22: error: pure-specifier on function-definition
  • When an abstract class is inherited, ALL pure virtual functions (except the pure virtual
    destructor
    ) must be *defined* by the *immediate* derived class, or the *immediate* derived
    class becomes abstract as well.

    In the following example:
    1. Class A is abstract.
    2. Class B inherits class A, but does NOT *define* pure virtual function A1, therefore it is
    also considered abstract.
    3. Class C inherits class B, which has become abstract due to the above stated reason, and
    therefore no object of class C can be created.

    Code:
    #include <iostream>
    using namespace std;
    
    class A
    {
    	public:
    		virtual void A1 () = 0;
    		virtual void A2 () = 0;
    };
    
    class B : public A
    {
    	// No definition of A1
    	
    	void A2 ()
    	{
    		// some definition of A2.
    	}
    };
    
    class C : public B
    {
    	
    };
    
    int main ()
    {
    	B objB;
    	C objC;
    	return 0;
    }
    Output:
    Code:
    anisha@linux-dopx:~> g++ x1.cpp
    x1.cpp: In function ‘int main()’:
    x1.cpp:28:4: error: cannot declare variable ‘objB’ to be of abstract type ‘B’
    x1.cpp:12:1: note:   because the following virtual functions are pure within ‘B’:
    x1.cpp:7:16: note: 	virtual void A::A1()
    
    x1.cpp:29:4: error: cannot declare variable ‘objC’ to be of abstract type ‘C’
    x1.cpp:22:1: note:   because the following virtual functions are pure within ‘C’:
    x1.cpp:7:16: note: 	virtual void A::A1()
  • The below example shows how the "in-directly" derived class C does NOT re-define
    the grand parent class abstract class's pure virtual functions, yet the compiler
    does NOT complain.
    Code:
    #include <iostream>
    using namespace std;
    
    class A
    {
    	public:
    		virtual void A1 () = 0;
    		virtual void A2 () = 0;
    };
    
    class B : public A
    {
    	// Redefining the base class's pure virtual function A1
    	void A1 ()
    	{
    	}
    	// Redefining the base class's pure virtual function A2
    	void A2 ()
    	{
    	}
    };
    
    class C : public B
    {
    	// Not redefining any function of the inherited classes.
    };
    
    int main ()
    {
    	B objB;
    	C objC;
    	return 0;
    }
Views 915 Comments 0
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 09:44 AM.

Main Menu
Advertisement

My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration