[23] Inheritance — what your mother never told you
(Part of C++ FAQ Lite, Copyright © 1991-2000, Marshall Cline, cline@parashift.com)


FAQs in section [23]:


[23.1] When my base class's constructor calls a virtual function, why doesn't my derived class's override of that virtual function get invoked?

During the class Base's constructor, the object isn't yet a Derived, so if Base::Base() calls a virtual function virt(), the Base::virt() will be invoked, even if Derived::virt() exists.

Similarly, during Base's destructor, the object is no longer a Derived, so when Base::~Base() calls virt(), Base::virt() gets control, not the Derived::virt() override.

You'll quickly see the wisdom of this approach when you imagine the disaster if Derived::virt() touched a member object from class Derived. In particular, if Base::Base() called the virtual function virt(), this rule causes Base::virt() to be invoked. If it weren't for this rule, Derived::virt() would get called before the Derived part of a Derived object is constructed, and Derived::virt() could touch unconstructed member objects from the Derived part of a Derived object. That would be a disaster.

TopBottomPrevious sectionNext section ]


[23.2] Should a derived class replace ("override") a non-virtual function from a base class?

It's legal, but it ain't moral.

Experienced C++ programmers will sometimes redefine a non-virtual function for efficiency (e.g., if the derived class implementation can make better use of the derived class's resources) or to get around the hiding rule. However the client-visible effects must be identical, since non-virtual functions are dispatched based on the static type of the pointer/reference rather than the dynamic type of the pointed-to/referenced object.

TopBottomPrevious sectionNext section ]


[23.3] What's the meaning of, Warning: Derived::f(float) hides Base::f(int)?

It means you're going to die.

Here's the mess you're in: if Base declares a member function f(int), and Derived declares a member function f(float) (same name but different parameter types and/or constness), then the Base f(int) is "hidden" rather than "overloaded" or "overridden" (even if the Base f(int) is virtual).

Here's how you get out of the mess: Derived must have a using declaration of the hidden member function. For example,

 class Base {
 public:
   void f(int);
 };
 
 class Derived : public Base {
 public:
   using Base::f;    
// This un-hides Base::f(int)
   void f(double);
 };

If the using syntax isn't supported by your compiler, redefine the hidden Base member function(s), even if they are non-virtual. Normally this re-definition merely calls the hidden Base member function using the :: syntax. E.g.,

 class Derived : public Base {
 public:
   void f(double);
   void f(int i) { Base::f(i); }  
// The redefinition merely calls Base::f(int)
 };

TopBottomPrevious sectionNext section ]


[23.4] What does it mean that the "virtual table" is an unresolved external?

If you get a link error of the form "Error: Unresolved or undefined symbols detected: virtual table for class Fred," you probably have an undefined virtual member function in class Fred.

The compiler typically creates a magical data structure called the "virtual table" for classes that have virtual functions (this is how it handles dynamic binding). Normally you don't have to know about it at all. But if you forget to define a virtual function for class Fred, you will sometimes get this linker error.

Here's the nitty gritty: Many compilers put this magical "virtual table" in the compilation unit that defines the first non-inline virtual function in the class. Thus if the first non-inline virtual function in Fred is wilma(), the compiler will put Fred's virtual table in the same compilation unit where it sees Fred::wilma(). Unfortunately if you accidentally forget to define Fred::wilma(), rather than getting a Fred::wilma() is undefined, you may get a "Fred's virtual table is undefined". Sad but true.

TopBottomPrevious sectionNext section ]


E-Mail E-mail the author
C++ FAQ LiteTable of contentsSubject indexAbout the author©Download your own copy ]
Revised Jul 10, 2000