Search code examples
c++hyperlinkvirtualvtable

Confused about non pure virtual classes in C++, what are they for?


I have a class declared as follow:

class TestFoo {
public:
    TestFoo();
    virtual void virtualFunction();
    void nonVirtualFunction();
};

that I try to implement this way

TestFoo::TestFoo(){}
void TestFoo::nonVirtualFunction(){}

which on compilation returns the error:

undefined reference to vtable for TestFoo

I tried :

TestFoo::TestFoo(){}
void TestFoo::nonVirtualFunction(){}
void TestFoo::virtualFunction(){}

which compiles ok which is consistent to the answers to these posts:

Undefined reference to vtable

undefined reference to vtable

What confuses me is that I thought the whole point of declaring a virtual function is that I would not need to define it. In this example, I am not planning to create any instance of TestFoo, but to create instances of (concrete) classes inheriting from TestFoo. But still, I want to define the function nonVirtualFunction for every subclasses of TestFoo.

Something I did not get right ?

Thanks !


Solution

  • Your description matches perfectly with the case of an abstract class. Declare your virtual function as:

        virtual void VirtualFunction () = 0;
    

    This means that you are not implementing the function in this class. As a result, the class becomes abstract. That is, no bare objects of this class can be instantiated.

    Also, you should provide a virtual destructor.

    Update: Some clarifications...

    The language allows you to redefine a non-virtual function. Though, the wrong version might be called in some cases:

    derived D;    // rB is a reference to base class but it
    base & rB=D;  // points to an object of the derived class
    
    rB.NonVirtualFunction ();  // The base-class version is called
    

    For this reason, redefining a non-virtual function is strongly discouraged nowadays. See Scott Meyers' "Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs", item 36: "Never redefine an inherited non-virtual function."

    See also item 7: "Declare destructors virtual in polymorphic base classes". An example:

    base * pB = new derived;
    delete pB;                // If base's destructor is not virtual,
                              // ~derived() will not be called.
    

    In case you wonder why isn't everything virtual by default, the reason is that calling a virtual function is slightly slower than calling a non-virtual one. Oh, and objects of classes with virtual functions occupy a few more bytes each.