C++ Inherited Virtual Function Declarations and Definitions

by Cliff Green, Copyright © 1996, 1998

This page last
updated on:

May 16, 2001

Contents and Related Links

CodeWrangler Pages

Overview

For many C programmers learning C++, virtual functions almost seem like magic. Once they are studied and used a little bit, however, they are usually both easy to understand and easy to design.

Sometimes the rules about declaring and defining virtual functions are not so easy to remember, though, so this article is going to summarize and explain a few of these details, specifically signature matching and inherited virtual function definitions.

Note: This article is not a summary of what virtual functions are and the basics of how to use them, but rather a clarification of some of the finer points.

Signature Matching

The first rule to remember is that each derived class that declares a virtual function must exactly match the signature of the base class virtual function, including the return type. From Stroustrup, The C++ Programming Language, 2nd Edition:
If a class base contains a virtual function vf, and a class derived derived from it also contains a function vf of the same type, then a call of vf for an object of class derived invokes derived::vf (even if the access is through a pointer or reference to base). The derived class function is said to override the base class function. If the function types are different, however, the functions are considered different and the virtual mechanism is not invoked. It is an error for a derived class function to differ from a base class' virtual function in the return type only.
There has been a relaxation of the return type rule for one case -- a derived virtual function can return a derived pointer or reference, e.g. a D* or D&, where the base virtual function returns a base pointer or reference, a B* or B&, and where D is a direct or indirect derived class of B. For more explanation see Stroustrup, The Design and Evolution of C++, section 13.7.

Inherited Virtual Function Definitions

If a derived class omits a virtual function declaration and definition, the definition is inherited from it's immediate base class. In the past, I explained that the definition came from the first base class that declared the virtual function -- in essence the 'root' base class for that particular virtual function. But after looking up some references and trying some test code on a couple of compilers, I found that I was wrong. It also makes sense from the compiler implementation point of view because the compiler has all the information from the immediate base class to properly construct the derived class vtable. From Stroustrup, The C++ Programming Language, 2nd Edition:
... A virtual function that has been defined in a base class need not be defined in a derived class. If it is not, the function defined for the base class is used in all calls.
Here's some example code and output:
#include <iostream>

using std::cout;

class A {
private:
  int x;
public:
  virtual void f() { cout << "Inside A::f\n"; }
};

class B : public A {
private:
  int y;
public:
  virtual void f() { cout << "Inside B::f\n"; }
};

class C : public B {
private:
  int z;
public:
  //    virtual void f() { cout << "Inside C::f\n"; }
};

int main () {
  A a_obj;
  B b_obj;
  C c_obj;

  A* a_ptr = &a_obj;
  a_ptr->f();
  a_ptr = &b_obj;
  a_ptr->f();
  a_ptr = &c_obj;
  a_ptr->f();
  return 0;
}
will print:
Inside A::f
Inside B::f
Inside B::f
and not
Inside A::f
Inside B::f
Inside A::f
as I previously thought.

This page constructed by Cliff Green, Copyright © 2001.