Navigation



12.6 — Pure virtual functions, abstract base classes, and interface classes

Finally, we arrive at the end of our long journey through inheritance! This is the last topic we will cover on the subject. So congratulations in advance on making it through the hardest part of the language!

Pure virtual (abstract) functions and abstract base classes

So far, all of the virtual functions we have written have a body (a definition). However, C++ allows you to create a special kind of virtual function called a pure virtual function (or abstract function) that has no body at all! A pure virtual function simply acts as a placeholder that is meant to be redefined by derived classes.

To create a pure virtual function, rather than define a body for the function, we simply assign the function the value 0.

class Base
{
public:
    const char* SayHi() { return "Hi"; } // a normal non-virtual function    

    virtual const char* GetName() { return "Base"; } // a normal virtual function

    virtual int GetValue() = 0; // a pure virtual function
};

When we add a pure virtual function to our class, we are effectively saying, “it is up to the derived classes to implement this function”.

Using a pure virtual function has two main consequences: First, any class with one or more pure virtual functions becomes an abstract base class, which means that it can not be instantiated! Consider what would happen if we could create an instance of Base:

int main()
{
    Base cBase; // pretend this was legal
    cBase.GetValue(); // what would this do?
}

Second, any derived class must define a body for this function, or that derived class will be considered an abstract base class as well.

Let’s take a look at an example of a pure virtual function in action. In a previous lesson, we wrote a simple Animal base class and derived a Cat and a Dog class from it. Here’s the code as we left it:

#include <string>
class Animal
{
protected:
    std::string m_strName;

    // We're making this constructor protected because
    // we don't want people creating Animal objects directly,
    // but we still want derived classes to be able to use it.
    Animal(std::string strName)
        : m_strName(strName)
    {
    }

public:
    std::string GetName() { return m_strName; }
    virtual const char* Speak() { return "???"; }
};

class Cat: public Animal
{
public:
    Cat(std::string strName)
        : Animal(strName)
    {
    }

    virtual const char* Speak() { return "Meow"; }
};

class Dog: public Animal
{
public:
    Dog(std::string strName)
        : Animal(strName)
    {
    }

    virtual const char* Speak() { return "Woof"; }
};

We’ve prevented people from allocating objects of type Animal by making the constructor protected. However, there’s one problem that has not been addressed. It is still possible to create derived classes that do not redefine Speak(). For example:

class Cow: public Animal
{
public:
    Cow(std::string strName)
        : Animal(strName)
    {
    }

    // We forgot to redefine Speak
};

int main()
{
    Cow cCow("Betsy");
    cout << cCow.GetName() << " says " << cCow.Speak() << endl;
}

This will print:

Betsy says ???

What happened? We forgot to redefine Speak, so cCow.Speak() resolved to Animal.Speak(), which isn’t what we wanted.

A better solution to this problem is to use a pure virtual function:

#include <string>
class Animal
{
protected:
    std::string m_strName;

public:
    Animal(std::string strName)
        : m_strName(strName)
    {
    }

    std::string GetName() { return m_strName; }
    virtual const char* Speak() = 0; // pure virtual function
};

There are a couple of things to note here. First, Speak() is now a pure virtual function. This means Animal is an abstract base class, and can not be instantiated. Consequently, we do not need to make the constructor protected any longer (though it doesn’t hurt). Second, because our Cow class was derived from Animal, but we did not define Cow::Speak(), Cow is also an abstract base class. Now when we try to compile this code:

class Cow: public Animal
{
public:
    Cow(std::string strName)
        : Animal(strName)
    {
    }

    // We forgot to redefine Speak
};

int main()
{
    Cow cCow("Betsy");
    cout << cCow.GetName() << " says " << cCow.Speak() << endl;
}

The compiler will give us a warning because Cow is an abstract base class and we can not create instances of abstract base classes:

C:\\Test.cpp(141) : error C2259: 'Cow' : cannot instantiate abstract class due to following members:
        C:\Test.cpp(128) : see declaration of 'Cow'
C:\\Test.cpp(141) : warning C4259: 'const char *__thiscall Animal::Speak(void)' : pure virtual function was not defined

This tells us that we will only be able to instantiate Cow if Cow provides a body for Speak().

Let’s go ahead and do that:

class Cow: public Animal
{
public:
    Cow(std::string strName)
        : Animal(strName)
    {
    }

    virtual const char* Speak() { return "Moo"; }
};

int main()
{
    Cow cCow("Betsy");
    cout << cCow.GetName() << " says " << cCow.Speak() << endl;
}

Now this program will compile and print:

Betsy says Moo

A pure virtual function is useful when we have a function that we want to put in the base class, but only the derived classes know what it should return. A pure virtual function makes it so the base class can not be instantiated, and the derived classes are forced to define these function before they can be instantiated. This helps ensure the derived classes do not forget to redefine functions that the base class was expecting them to.

Interface classes

An interface class is a class that has no members variables, and where all of the functions are pure virtual! In other words, the class is purely a definition, and has no actual implementation. Interfaces are useful when you want to define the functionality that derived classes must implement, but leave the details of how the derived class implements that functionality entirely up to the derived class.

Interface classes are often named beginning with an I. Here’s a sample interface class:

class IErrorLog
{
    virtual bool OpenLog(const char *strFilename) = 0;
    virtual bool CloseLog() = 0;

    virtual bool WriteError(const char *strErrorMessage) = 0;
};

Any class inheriting from IErrorLog must provide implementations for all three functions in order to be instantiated. You could derive a class named FileErrorLog, where OpenLog() opens a file on disk, CloseLog() closes it, and WriteError() writes the message to the file. You could derive another class called ScreenErrorLog, where OpenLog() and CloseLog() do nothing, and WriteError() prints the message in a pop-up message box on the screen.

Now, let’s say you need to write some code that uses an error log. If you write your code so it includes FileErrorLog or ScreenErrorLog directly, then you’re effectively stuck using that kind of error log. For example, the following function effectively forces callers of MySqrt() to use a FileErrorLog, which may or may not be what they want.

double MySqrt(double dValue, FileErrorLog &cLog)
{
    if (dValue < 0.0)
    {
        cLog.WriteError("Tried to take square root of value less than 0");
        return 0.0;
    }
    else
        return dValue;
}

A much better way to implement this function is to use IErrorLog instead:

double MySqrt(double dValue, IErrorLog &cLog)
{
    if (dValue < 0.0)
    {
        cLog.WriteError("Tried to take square root of value less than 0");
        return 0.0;
    }
    else
        return dValue;
}

Now the caller can pass in any class that conforms to the IErrorLog interface. If they want the error to go to a file, they can pass in an instance of FileErrorLog. If they want it to go to the screen, they can pass in an instance of ScreenErrorLog. Or if they want to do something you haven’t even thought of, such as sending an email to someone when there’s an error, they can derive a new class from IErrorLog (eg. EmailErrorLog) and use an instance of that! By using IErrorLog, your function becomes more independent and flexible.

Interface classes have become extremely popular because they are easy to use, easy to extend, and easy to maintain. In fact, some modern languages, such as Java and C#, have added an “interface” keyword that allows programmers to directly define an interface class without having to explicitly mark all of the member functions as abstract. Furthermore, although Java and C# will not let you use multiple inheritance on normal classes, they will let you multiply inherit as many interfaces as you like. Because interfaces have no data and no function bodies, they avoid a lot of the traditional problems with multiple inheritance while still providing much of the flexibility.

13.1 — Input and output (I/O) streams
Index
12.5 — The virtual table

29 comments to 12.6 — Pure virtual functions, abstract base classes, and interface classes

  • Susan

    Can you please answer why a pure virtual function should be equated to 0 and not to any other number.

    • As far as I know, =0 is just a syntactic convention for letting the compiler know that this is a pure virtual function.

      You can think about it this way: normal functions have a body of code that needs to be executed when they are called. This code has to live somewhere in memory, so the function’s name is essentially a pointer to that code.

      On the other hand, pure virtual functions have no body, and thus, do not have need for an address at all. 0 is the NULL address.

    • Jim

      I read this today, they didn’t want to add any more reserved words such as “pure” and it was moving too far from the C language, so this hotchpotch =0 stuff was used instead

    • w0rkbean

      As someone said earlier, it’s a syntactic convention. I think the reason for that convetion can be explained as ” as we know the function name itself is a pointer to that function just like array name is a pointer to the first element of that array. So if you are equating that pointer to 0 which is a NULL, makes it a NULL pointer”. So the essence is equating the function to 0 is like defing a NULL ponter which may point to a a valid address later on”

  • [...] 2007 Prev/Next Posts « 12.4 — Early binding and late binding | Home | 12.6 — Pure virtual functions, abstract base classes, and interface classes » Friday, February 8th, 2008 at 3:29 [...]

  • Sean

    Great tutorial for interface class,
    Thanks a lot!

  • Ben

    Hi Alex,
    in your IErrorLog class all functions are private. As i tried to compile your code, with the MySqrt() function, i discoverd, that the compiler complains about that, so i defined a class inheriting IErrorLong and changing the scope of the functions to public; still the compiler insists not to compile the code. So you might want to change the code. Besides that, can you imagine why a virtual class should ever have private member functions?
    Ben

    • Hi Ben,

      I agree with you, the functions need to be public. My code did compile – the only thing
      I needed to be sure about was that the IErrorLog parameter to MySqrt was a pointer or reference.
      If it’s passed by value the compiler tries to instantiate an IErrorLog object which it can’t do for an abstract class.

      Grant

  • Balaji

    Very good tutorial for beginers,

  • Eugene Wee

    A pure virtual function can be defined (as in have a body). One case where that is useful is when the base class implementer wishes to allow derived classes access to some default implementation, but require that concrete derived classes override that member function nonetheless.

    [ Thanks, I wasn't aware of that. -Alex ]

  • tvraju

    “First, any class with one or more virtual functions becomes an abstract base class,”,
    the text should be one or more “pure virtual functions” instead of virtual functions.

    [ Thanks! It's fixed now. -Alex ]

  • E-man_96@live.com

    I have read 2 other tutorials and this one is the one that has “everything”.

  • sudheer

    Wonderful tutorial on Pure Virtual functions. Kudos Alex

  • Quick nitpick on the HTML in this page – the top of the page with next/previous post lists 7.13 as the next topic instead of 13.1.

    P.S.: Excellent website for learning C++. Thank you very much for providing this resource. I’ll be sure to refer people here when appropriate!

  • LJ

    this is definitely the best tutorial i’ve found so far on c++. great work!
    another quick nitpick: the mySqrt function does not take the square root :)

  • ricky

    just a simple program..

    #include "stdafx.h"
    #include "iostream"
    #include "conio.h"
    using namespace std;
    
    class base
    {
    	public :
    	int x;
    	virtual void display();
    };
    void base::display()
    {
    	x =100;
    	cout<<x<<" Display Base"<<endl;
    }
    class derived : public base
    {
    	void display();
    };
    void derived::display()
    {
    	x =50;cout<<x<<" Display Derived";
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
    	base B1;
    	derived d1;
    	base *b1ptr;
    	b1ptr = &B1;
    	b1ptr->display();
    
    	b1ptr = &d1;
    
    	b1ptr->display();
    	//d1.base::display();
    	getch();
    	return 0;
    }

    )

    my doubt:

    How am I able to access the private member of derived class function (**which is private) using base class pointer??

  • Kathy

    petrfect tutorial~~

    I have learned a lot…

  • gans

    Hi,
    As reply to Ricky’s question:

    In C++ there is also a concept called “Late binding yet static typing”. That is
    When you have a pointer to object and object is derived from the type of class of type pointer, there are two types,1) type of the pointer: static 2) type of pointed-to-object: dynamic.
    Here static typing means, the legality of the function call is determined by the compiler at compile time, since pointer is Base and Base has public virtual function. compiler validates the function calling. but at run time, since you have assigned the derived object address, it resolves the derived function only.

    Hope this helps u.

  • saurabh

    I learned a lot from your tutorials and kudos to you

    It will be great if you can add two more topics to this chapter

    1) We can define body for a pure virtual function so please add when, why and how ?
    2) Please add virtual table view for abstract class why compiler not letting us to instantiate abstract class or i should say class having and pure virtual function

    Here is my views:
    we can not make object of abstract class because, in the vtable the vtable entry for the abstract class functions will be NULL, even if there is a single pure virtual function in the class the class becomes as abstract class.Even if there is a single NULL entry in the function table the compiler does not allow to create the object.

  • bantoo011

    How is the vtable for abstract & interface class looks like ?

  • warzix

    Great article, although I should add one comment about the Interface class definition:

    “An interface class is a class that has no members variables, and where all of the functions are pure virtual! In other words, the class is purely a definition, and has no actual implementation.”

    Effectively, my comment is after the example below:

    Suppose you define the following Interface

    class ISomething {
    public:
    virtual void doStuff1() = 0;
    //… bunch of other definitions
    };

    and you have a class that implements it:

    class Impl : public ISomething {
    private:
    char* myCharPtr;
    public:
    void doStuff1() { /* do ‘stuff’ */ };
    // implement all other stuff
    /* Constructor that allocates memory */
    Impl() { myCharPtr = new char[10]; }
    /* Destructor that deallocates memory */
    ~Impl() { delete[] myCharPtr; }
    };

    void main()
    {
    ISomething* ptr = new Impl; //upcasting. ISomething pointer points to Impl object…

    delete ptr; //cleaning up memory…
    // This effectivelly invokes the default destructor on ISomething which is not virtual and therefore would not resolve to ~Impl()
    // therefore this can lead to memory leaks (as shown in the example) or any other problems related to missing destructor calls.
    }

    I think it is worth a comment about that right after the phrase I’ve quoted such as:
    “The only exception is the destructor which should be virtual and implemented if the Interface is supposed to be used as a “placeholder” for pointers to derived classes’ objects…”.

    Best Regards

  • [...] pure virtual function ???? [...]

  • [...] article at http://www.learncpp.com/cpp-tutorial/126-pure-virtual-functions-abstract-base-classes-and-interface-… claims that you a compile error because “Cow is an abstract base class and we can not create [...]

  • [...] article at http://www.learncpp.com/cpp-tutorial/126-pure-virtual-functions-abstract-base-classes-and-interface-… claims that you have a compile error because “Cow is an abstract class and we can not create [...]

You must be logged in to post a comment.