Introduction This article talks about Virtual Table and _vptr in Replicated Multiple Inheritance and in Virtual Base Class (or Shared Multiple Inheritance). Here it is explained using an example: In this example, we have Base1, Base2, Base3 and Derive classes, where Base2 and Base3 classes are derived from Base1 class and Derive class is derived from Base2 and Base3 classes. Background Replicated Multiple Inheritance: Here, Base2 and Base3 classes are derived Normally from Base1 class, there is a duplicate data and methods of Base1 class to Derive class (from Base2 and Base3 classes) and when we try to access that common data or functions through Derive object, there will be a ambiguity in accessing it. As I have already explained in my last artcile (it is listed in reference part here), in Mupltile Inheritance, Derive classes (which has been derived from more than one base class) will have it's Base classe's VPTR with it. And it's own virtual functions will be listed as part of it's first Base classes virtual table. For Replicated MI example, if we take teh object memory map for Derive class's object, functions and data of it's base classes will be listed as below: vptr and data of class Base2 - contains virtual methods of Base1, Base2(self), then Derive class's ones, i.e.: --------- Base1 class Virtual Methods Base2 class virtual Methods Base2 class data (if any) Derive class virtual Methods then vptr and data of class Base3 - contains virtual methods of Base1 and Base3 (self): --------- Base1 class Virtual Methods Base3 class Virtual Methods Base3 class Data (if any) Derive data ------------ Derive class Data Also Size of the Derive object would be: _vptr of Base2 class + data of Base2 class + _vptr of Base3 class + data of Base3 class + data of Derive class The same is explained here in this example code and o/p too is given: Here for this example, we can not have Data for Base1 class and if we try to have, will get a compilation error (amgibuous) for Base1's member data. If you, observe the memory map for object Derive d, the virtual functions of foremost base class i.e. Base1 class is duplicated in both the vtables of classes Base2 and Base3. The code Replicated Multiple Inheritance example Code: #include<iostream.h> class Base1 { public: virtual void func1(void){cout<<"Base1::func1\n";}; }; class Base2 : public Base1 { public: int a; virtual void func2(void){cout<<"Base2::func2\n";}; }; class Base3 : public Base1{ public: virtual void func3(void){cout<<"Base3::func3\n";}; }; class Derive: public Base2, public Base3 { public: int b; virtual void func4(void){cout<<"Derive::func4\n";}; }; typedef void (*fun) (void); int main() { Derive d; int* vptr; fun funp=NULL; cout<<"Size of Derive object d is = "<<sizeof(d)<<endl<<endl; cout<< "Memory map of Derive object d :\n"; cout<<"------------------------------------\n\n"; // calling virtual function func1 of Base1 funp = (fun)*((int*)*(int*)((int*)&d+0)+0); funp(); // calling virtual function func2 of Base2 funp = (fun)*((int*)*(int*)((int*)&d+0)+1); funp(); // calling virtual function func4 of Derive funp = (fun)*((int*)*(int*)((int*)&d+0)+2); funp(); // accessing and changing the variable of Base2 int* pInt = (int*)&d+1; *(pInt+0) = 30; cout<<"Base2 class data: a =" << d.a <<endl; // calling virtual function func1 of Base1 funp = (fun)*((int*)*(int*)((int*)&d+2)+0); funp(); // calling virtual function func3 of Base3 funp = (fun)*((int*)*(int*)((int*)&d+2)+1); funp(); // accessing and changing the variable of Derive pInt = (int*)&d+3; *(pInt+0) = 100; cout<<"Derive class data: b =" << d.b <<endl; return(0); } output ----- Size of Derive object d is = 16 Memory map of Derive object d : ------------------------------------ Base1::func1 Base2::func2 Derive::func4 Base2 class data: a =30 Base1::func1 Base3::func3 Derive class data: b =100 So for the above code (size of Derive object "d" is): 4 bytes (_vptr of Base2) + 4 bytes (data i.e. int a of Base2 class) + 4 bytes (_vptr of Base3 class) + 4 bytes (data i.e. int b of Derive class) that equates to 16 Here you can see the pictorial view of memory map for Derive class object Shared Multiple Inheritance or Virtual Base class As a solution for not to replicate the members and data of foremost base class, we go for Virtual Base classes. So, for our above example, we need to make class Base1 as Virtual base class for class Base2 and class Base3, then derive class Derive from Base2 and Base3. I have noticed 2 different memory-map for Derive object for Virual Base or Shared Multiple Inheritance as below: 1. When foremost base class has only virtual functions and no data to share. 2. When foremost base class has some data and/or virtual functions For the first case, if we check the memory map for Derive class object, it is as below i.e: vptr and data of Base2 class - contains foremost class i.e. Base1, Base2 and Derive class virtual methods: ---------- Base1 class Virtual Functions Base2 class Virtual Functions Derive class Virtual Functions Base2 data vptr and data of Base3 class - contains only Base3 virtual methods and contains pointers to Base1 class (common class) virtual methods ------------ Pointers to virtual functions of Base1 class Base3 class Virtual Methods Base3 data Data of Derive class ---------- Derive class data Also the Size of the Derive object would be: _vptr of Base2 class + data of Base2 class + _vptr of Base3 class + data of Base3 class + data of Derive class The same is explained here in this example code and o/p too is given: The code Shared Mutiple Inheritance without data eample Code: #include<iostream.h> class Base1 { public: virtual void func1(void){cout<<"Base1::func1\n";}; }; class Base2 : virtual public Base1 { public: int a; virtual void func2(void){cout<<"Base2::func2\n";}; }; class Base3 : virtual public Base1{ public: virtual void func3(void){cout<<"Base3::func3\n";}; }; class Derive: public Base2, public Base3 { public: int b; virtual void func4(void){cout<<"Derive::func4\n";}; }; typedef void (*fun) (void); int main() { Derive d; fun funp=NULL; cout<<"Size of Derive object d is = "<<sizeof(d)<<endl<<endl; cout<< "Memory map of Derive object d :\n"; cout<<"------------------------------------\n\n"; // calling virtual function func1 of Base1 funp = (fun)*((int*)*(int*)((int*)&d+0)+0); funp(); // calling virtual function func2 of Base2 funp = (fun)*((int*)*(int*)((int*)&d+0)+1); funp(); // calling virtual function func4 of Derive funp = (fun)*((int*)*(int*)((int*)&d+0)+2); funp(); // accessing and changing the variable of Base2 int* pInt = (int*)&d+1; *(pInt+0) = 30; cout<<"Base2 class Data: a =" << d.a <<endl; // calling virtual function func3 of Base3 funp = (fun)*((int*)*(int*)((int*)&d+2)+1); funp(); cout<<"Base3 class Data if any (there is no data for Base3 class here in example)" <<endl; // accessing and changing the variable of Derive pInt = (int*)&d+3; *(pInt+0) = 100; cout<<"Derive class Data: b =" << d.b <<endl<<endl; return(0); } output ----- Size of Derive object d is = 16 Memory map of Derive object d : ------------------------------------ Base1::func1 Base2::func2 Derive::func4 Base2 class Data: a =30 Base3::func3 Base3 class Data if any (there is no data for Base3 class here in example) Derive class Data: b =100 So for the above code (size of Derive object "d" is): 4 bytes (_vptr of Base2) + 4 bytes (data i.e. int a of Base2 class) + 4 bytes (_vptr of Base3 class) + 4 bytes (data i.e. int b of Derive class) that equates to 16 Here you can see the pictorial view of memory map for Derive class object For the second case i.e. if foremost class contains some data along with/without virtual functions, then object memory of Derive class object will be as shown below: vptr and data of Base2 class - contains only Base2 (self) and Derive class virtual methods: ---------- Base2 class Virtual Functions Derive class Virtual Functions Base2 data vptr and data of Base3 class - contains only Base3 virtual methods ------------ Base3 class Virtual Methods Base3 data Data of Derive object and vptr of foremost Base class and it's data ---------- Derive class data virtual functions of foremost class i.e. Base1 class Data of foremost class i.e. Base1 class Also Size of the Derive object would be: _vptr of Base2 class + data of Base2 class + _vptr of Base3 class + data of Base3 class + data of Derive class + _vptr of Base1 class + data of Base1 class The same is explained here in this example code and o/p too is given: The code Shared Multiple Inheritance with Data Code: #include<iostream.h> class Base1 { public: virtual void func1(void){cout<<"Base1::func1\n";}; int a; }; class Base2 : virtual public Base1 { public: int b; virtual void func2(void){cout<<"Base2::func2\n";}; }; class Base3 : virtual public Base1{ public: virtual void func3(void){cout<<"Base3::func3\n";}; }; class Derive: public Base2, public Base3 { public: int c; virtual void func4(void){cout<<"Derive::func4\n";}; }; typedef void (*fun) (void); int main() { Derive d; fun funp=NULL; cout<<"Size of Derive object d is = "<<sizeof(d)<<endl<<endl; cout<< "Memory map of Derive object d :\n"; cout<<"------------------------------------\n\n"; // calling virtual function func1 of Base2 funp = (fun)*((int*)*(int*)((int*)&d+0)+0); funp(); // calling virtual function func4 of Derive funp = (fun)*((int*)*(int*)((int*)&d+0)+1); funp(); // accessing and changing the variable of Base2 int* pInt = (int*)&d+1; *(pInt+0) = 30; cout<<"Base2 class Data: b =" << d.b <<endl; // calling virtual function func3 of Base3 funp = (fun)*((int*)*(int*)((int*)&d+2)+0); funp(); cout<<"Base3 class Data if any (there is no data for Base3 class here in example)" <<endl; // accessing and changing the variable of Derive pInt = (int*)&d+3; *(pInt+0) = 60; cout<<"Derive class Data: c =" << d.c <<endl; // calling virtual function func1 of Base1 funp = (fun)*((int*)*(int*)((int*)&d+4)+0); funp(); // accessing and changing the variable of Base1 pInt = (int*)&d+5; *(pInt+0) = 120; cout<<"Base1 class Data: a =" << d.a <<endl<<endl; return(0); } output ----- solutionWithData.cc Size of Derive object d is = 24 Memory map of Derive object d : ------------------------------------ Base2::func2 Derive::func4 Base2 class Data: b =30 Base3::func3 Base3 class Data if any (there is no data for Base3 class here in example) Derive class Data: c =60 Base1::func1 Base1 class Data: a =120 So for the above code (size of Derive object "d" is): 4 bytes (_vptr of Base2 class) + 4 bytes (data i.e. int b of Base2 class) + 4 bytes (_vptr of Base3 class) + 4 bytes (data i.e. int c of Derive class) 4 bytes (_vptr of Base1 class) + 4 bytes (data i.e. int a of Base1 class) that eqautes to 24 If you notice here, the size of the Derive object differs in both the cases as explained above. Here you can see the pictorial view of memory map for Derive class object References How Virtual Table and _vptr works How Virtual Table and _vptr works Virtual Table and _vptr in Multiple Inheritance Virtual Table and _vptr in Multiple Inheritance