When a derived class inherited the properties of n Base classes each with one virtual function, while constructing the virtual table for the derived class, why the compiler constructs an individual virtual table for each Base class? Why the compiler is not constructing a single virtual table consisting of all references for virtual functions of Base class and its own?
For example: In following program, the derived class inherited 3 Base classes each with one virtual function.
class Base1
{
public:
virtual void base1_func1(){cout<<"In Base1:base1_func1:"<<endl;}
};
class Base2
{
public:
virtual void base2_func1(){cout<<"In Base2:base2_func1:"<<endl;}
};
class Base3
{
public:
virtual void base3_func1(){cout<<"In Base3:base3_func1:"<<endl;}
};
class Derived:public Base1, public Base2, public Base3
{
};
typedef void (*Func) (void);
int main()
{
Base1 b1;
Base2 b2;
Base3 b3;
Derived d;
Func f= NULL;
cout<<"Size of Base1 obj:"<<sizeof(b1)<<endl;
cout<<"Size of Base2 obj:"<<sizeof(b2)<<endl;
cout<<"Size of Base3 obj:"<<sizeof(b3)<<endl;
cout<<"Size of Derived obj:"<<sizeof(d)<<endl;
cout<<"Printing the VPTR Address of Base1 obj b1 :"<< *((int *)(&b1)+0)<<endl;
cout<<"Printing the Address of Base1 func1 in VTABLE:"<< (int *)*((int *)*((int *)(&b1)+0)+0)<<endl;
f = (Func)*((int *)*((int *)(&b1)+0)+0);
f();
cout<<"Printing the VPTR Address of Base2 obj b2 :"<< *((int *)(&b2)+0)<<endl;
cout<<"Printing the Address of Base2 func1 in VTABLE:"<< (int *)*((int *)*((int *)(&b2)+0)+0)<<endl;
f = (Func)*((int *)*((int *)(&b2)+0)+0);
f();
cout<<"Printing the VPTR Address of Base3 obj b3 :"<< *((int *)(&b3)+0)<<endl;
cout<<"Printing the Address of Base3 func1 in VTABLE:"<< (int *)*((int *)*((int *)(&b3)+0)+0)<<endl;
f = (Func)*((int *)*((int *)(&b3)+0)+0);
f();
cout<<"Printing the VPTR1 Address of Derived obj d :"<< *((int *)(&d)+0)<<endl;
cout<<"Printing the VPTR2 Address of Derived obj d :"<< *((int *)(&d)+1)<<endl;
cout<<"Printing the VPTR3 Address of Derived obj d :"<< *((int *)(&d)+2)<<endl;
cout<<"Printing the Address of Derived base1_func1 in VTABLE:"<< (int *)*((int *)*((int *)(&d)+0)+0)<<endl;
f = (Func)*((int *)*((int *)(&d)+0)+0);
f();
cout<<"Printing the Address of Derived base2_func1 in VTABLE:"<< (int *)*((int *)*((int *)(&d)+1)+0)<<endl;
f = (Func)*((int *)*((int *)(&d)+1)+0);
f();
cout<<"Printing the Address of Derived base3_func1 in VTABLE:"<< (int *)*((int *)*((int *)(&d)+2)+0)<<endl;
f = (Func)*((int *)*((int *)(&d)+2)+0);
f();
return 0;
}
Output:
Size of Base1 obj:4
Size of Base2 obj:4
Size of Base3 obj:4
Size of Derived obj:12
Printing the VPTR Address of Base1 obj b1 :134517392
Printing the Address of Base1 func1 in VTABLE:0x8048dfe
In Base1:base1_func1:
Printing the VPTR Address of Base2 obj b2 :134517424
Printing the Address of Base2 func1 in VTABLE:0x8048e2a
In Base2:base2_func1:
Printing the VPTR Address of Base3 obj b3 :134517456
Printing the Address of Base3 func1 in VTABLE:0x8048e56
In Base3:base3_func1:
Printing the VPTR1 Address of Derived obj d :134517512
Printing the VPTR2 Address of Derived obj d :134517524
Printing the VPTR3 Address of Derived obj d :134517536
Printing the Address of Derived base1_func1 in VTABLE:0x8048dfe
In Base1:base1_func1:
Printing the Address of Derived base2_func1 in VTABLE:0x8048e2a
In Base2:base2_func1:
Printing the Address of Derived base3_func1 in VTABLE:0x8048e56
In Base3:base3_func1:
The output clearly says that complier constructs an individual virtual table for each Base class inherited in derived class.