When the compiler sees the keyword virtual in a class's statement, it automatically creates a virtual pointer and corresponding virtual table for each class (i.e. the base and all derived classes).
When a method of a derived object is invoked a lookup is made using its vpointer that points to its vtable for a corresponding address, if the class has its own method that address will be used, if not the address of the base (inherited) method will be used.
This example shows two derived classes with their own version of the base classes methods. Just for clarity, I have shown what happens when the derived classes methods are invoked, and also what happens when it hasn't overridden the base method (i.e. it falls back to the base method):
#include <iostream> #include <string> using namespace std; class Animal { public: virtual void speak() { cout << "Base: Mumblings from the primordial soup. " << endl ; } virtual void walk() { cout << "Base: Bumping into things." << endl ; } virtual ~Animal(){} }; class Cat : public Animal { public : void speak(){ cout << "Derived: Meow." << endl ; } virtual ~Cat(){} }; class Dog : public Animal { public : void walk(){ cout << "Derived: Running after tail at 10mph" << endl ; } virtual ~Dog(){} }; int main() { Animal cell ; //create new instance of base class object Animal *ptr = &cell; //create a base class (data type) pointer and assign the address of cell ptr->speak() ; //invoke its speak method ptr->walk() ; //invoke its walk method Cat silver ; //declare a Cat object called silver, derived from Animal ptr = &silver ; //assign the address of silver to the base class (data type) pointer ptr->speak() ; //invoke the derived overridden speak method ptr->walk() ; //invoke the inherited walk method Dog rex ; //declare a Dog object called rex, derived from Animal ptr = &rex ; //assign the address of rex to the base class (data type) pointer ptr->speak() ; //invoke the inherited speak method ptr->walk() ; //invoke the derived overridden walk method return 0; }
Compile & Run:
Base: Mumblings from the primordial soup. Base: Bumping into things. Derived: Meow. Base: Bumping into things. Base: Mumblings from the primordial soup. Derived: Running after tail at 10mph |
We can see the base class object calls its own methods on lines 1 & 2 of the output. Line 3 shows the Cat derived object (silver) invoking its correct overridden method, but on line 4 has to fall back to the base method. Similarly, line 5 shows the Dog derived object (rex) falling back to the base method, but being able to invoke its correct overridden method on line 6.