Virtual Functions and Runtime Polymorphism in C++ | How Virtual Table and _vptr works

Runtime Polymorphism is C++ is achieved with a virtual function. Hence in order to implement the runtime behavior, C++ compiler inserts Virtual Table for every class having virtual function or class inherited from the class that has a virtual function.

vtable: A table of function pointers. It is maintained per class.
vptr: A pointer to vtable. It is maintained per object


Implementation:

#include

class Base  
 {  
 public:  
    virtual void function1() {cout<<"Base :: function1()\n";};  
    virtual void function2() {cout<<"Base :: function2()\n";};  
    virtual ~Base(){};
};  
   
class D1: public Base  
{  
public:  
   ~D1(){};
   virtual void function1() { cout<<"D1 :: function1()\n";};
};  
  
class D2: public Base  
{  
public:  
   ~D2(){};
   virtual void function2() { cout<< "D2 :: function2\n";};  
};  

int main()
{
  D1 *d = new D1;;
  Base *b = d; 

  b->function1();
  b->function2();

  delete (b);
  
  return (0);
}

output:
D1 :: function1()
Base :: function2()




Explanation :

Here in function main b pointer gets assigned to D1's _vptr and now starts pointing to D1's vtable. Then calling to a function1(), makes it's _vptr straightway calls D1's vtable function1() and so in turn calls D1's method i.e. function1() as D1 has it's own function1() defined its class.

Whereas pointer b calling to a function2(), makes it's _vptr points to D1's vtable which in-turn pointing to Base class's vtable function2 () as shown in the diagram (as D1 class does not have it's own definition or function2()).

So, now calling delete on pointer b follows the _vptr - which is pointing to D1's vtable calls it's own class's destructor i.e. D1 class's destructor and then calls the destructor of Base class - this as part of when a dervied object gets deleted it turn deletes it's embedded base object. That's why we must always make Base class's destructor as virtual if it has any virtual functions in it.

Bottom Line:
That's how the Run-time or Dynamic binding happens by calling virtual functions of different derived objects.

Comments