The first element of the class is usuaylly the (hidden) vtable pointer - vptr. For a polymorphic class, the vtable is first initialized to the vtable of base class in the base class constructor. Then, when the derived class constructor executes the same vtable pointer is initialized to point to the derived class vtable. Note that the base class vtable points to base version of function1 and function2 whereas derived class vtable points to derived version of function1 and function2.
Now, when a pointer to base class points to an instance of derived class, this is what 'typically may' happen:
class base
{
//int* vptr; //hidden vtable pointer, created by compiler for polymorphic class. vptr points to base class vtable for base clas objects
public:
virtual void function1(){std::cout <<"base::function1()"<<std::endl;}
virtual void function2(){std::cout <<"base::function2()"<<std::endl;}
};
class derived: public base
{
//int* vptr; //hidden vtable pointer, inherited from the base class. vptr points to derived class vtable for derived class objects
public:
virtual void function1(){std::cout <<"derived::function1()"<<std::endl;}
virtual void function2(){std::cout <<"derived::function2()"<<std::endl;}
};
int main()
{
typedef void (*vtableFnPtr)();
base* pBase;
base base_obj;
derived derived_obj;
pBase = &derived_obj; //base pointer pointing to derived object
//one of the several possible implementations by compiler
int* vtableCallBack = *(int**)&derived_obj; //read the address of vtable pointed by the hidden vptr in the derived_obj
//pBase->function1();
((vtableFnPtr)vtableCallBack[0])(); //calls derived::function1(), when application calls pBase->function1();
//pBase->function2();
((vtableFnPtr)vtableCallBack[1])(); //calls derived::function2(), when application calls pBase->function2();
pBase = &base_obj;
//one of the several possible implementations by compiler
vtableCallBack = *(int**)&base_obj; //base pointer pointing to base object
//pBase->function1();
((vtableFnPtr)vtableCallBack[0])(); //calls base::function1(), when application calls pBase->function1();
//pBase->function2();
((vtableFnPtr)vtableCallBack[1])(); //calls base::function2(), when application calls pBase->function2();
}
Note that the C++ compiler does not say anything about the implementation methodology to be used for achieving polymorphic behavior and hence it is completly upto the compiler to use vtable or any other implementation as long as the behavior is polymorphic. However, vtable remains one of the most widely used methods to achieve polymorphic behavior.