Inheritance and virtual functions

The power of inheritance in C++ comes from virtual functions and dynamic binding. Dynamic binding realizes the polymorphism inherent in the static type structure of the inheritance hierarchy in a dynamic way. Dynamic binding is illustrated by the example shown in slide 7-dispatching.

Virtual functions -- dispatching

  class A { 
A
public: virtual void operator()() { cout << "A"; } }; class B : public A {
B
public: virtual void operator()() { cout << "B"; } };

slide: Virtual functions -- dispatching

The class A defines a virtual member function (that results in printing A) which is redefined by a similar function in class B (which results in printing B). As an example of using the classes defined above, look at the following program fragment:
  A* a = new B(); (*a)(); 
produces B
In case the function would not have been defined as virtual, the outcome of applying it to (a pointer to) a B object would have been A, instead of B.

Explicit scoping

Virtual functions that are redefined in derived classes may still access the original version defined in the base class, as illustrated in slide 7-scoping.
Scoping may be used within a member function of the class as well as by a client (when invoking a member function) as illustrated below.
   A* a = new B(); a->A::operator()(); (*a)(); 
produces ABBA
The outcome of this statement is ABBA.
Such a scoping mechanism is certainly not unique to C++, although the notation for it is. In Smalltalk, the expression super may be used to access methods defined in the ancestor class, and in Eiffel one must use a combination of redefining and renaming to achieve this. As a remark, I prefer the use of operator()() when any other method name would be arbitrary. The attractiveness of operator()() is that it is used as a function application operator, as in (*a)().