The Virtual Pointer & Virtual Table

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.

Leave a Reply