Introduction
This article talks about how Virtual table and _vptr looks in case of simple Multiple Inheritance
Background
In Multiple Inheritance, the Derived class contains the _vptr of all it's Base classes.
Lets see the below example, where-in, derived class i.e. Derive is derived from
Base1, Base2 & Base3 classes.
Here is the example code and it's output for Simple Multiple Inheritance
The code
Code: Cpp
#include<iostream.h>
class Base1
{
public:
int a;
virtual void func1() { cout << "Base1::func1()" << endl; }
virtual void func2() { cout << "Base1::func2()" << endl; }
};
class Base2 {
public:
virtual void func1() { cout << "Base2::func1()" << endl; }
virtual void func2() { cout << "Base2::func2()" << endl; }
};
class Base3 {
public:
virtual void func1() { cout << "Base3::func1()" << endl; }
virtual void func2() { cout << "Base3::func2()" << endl; }
};
class Derive : public Base1, public Base2, public Base3
{
public:
int b;
virtual void disp1()
{
cout << "Derive::disp1" << endl;
}
virtual void Fnc()
{
cout << "Derive::disp2" << endl;
}
};
typedef void(*function)(void);
int main()
{
Derive obj;
function func = NULL;
//Size contains the _vptr of all it's base classes and Base class data and it's own
//Data
cout<<"Size of obj = "<<sizeof(obj)<<endl;
// calling 1st virtual function of Base1
func = (function)*((int*)*(int*)((int*)&obj+0)+0);
func();
// calling 2nd virtual function of Base1
func = (function)*((int*)*(int*)((int*)&obj+0)+1);
func();
//Next location contains the Base1's data, lets change it and check the o/p
int* pInt = (int*)&obj+1;
*(pInt+0) = 30;
cout<<"Base1 class fields: a =" << obj.a <<endl;
// calling 1st virtual function of Drive
func = (function)*((int*)*(int*)((int*)&obj+0)+2);
func();
// calling 2nd virtual function of Drive
func = (function)*((int*)*(int*)((int*)&obj+0)+3);
func();
// calling 1st virtual function of Base2
func = (function)*((int*)*(int*)((int*)&obj+2)+0);
func();
// calling 2nd virtual function of Base2
func = (function)*((int*)*(int*)((int*)&obj+2)+1);
func();
// calling 1st virtual function of Base3
func = (function)*((int*)*(int*)((int*)&obj+3)+0);
func();
// calling 2nd virtual function of Base3
func = (function)*((int*)*(int*)((int*)&obj+3)+1);
func();
//At the end, it contains it's own data i.e. Derive classes data, lets change it and
//check the o/p
pInt = (int*)&obj+4;
*(pInt+0) = 100;
cout<<"Derive class fields: b =" << obj.b <<endl;
return 0;
}
output
---------
Size of obj = 20
Base1::func1()
Base1::func2()
Base1 class fields: a =30
Derive::disp1
Derive::disp2
Base2::func1()
Base2::func2()
Base3::func1()
Base3::func2()
Derive class fields: b =100
Here is the diagram that shows _vptr s of all Derive's Base classes:

And as seen in the diagram, class Derive, contains the _vptr of all it's base classes.
Also, you can notice that, Derive class's only methods will be listed after it's first Base class's virtual methods i.e. class Base1
Here is the diagram that shows the complete picture of Derive class object i.e. obj in the code.

Wherein, it initially contains the first base class's i.e Base1's _vptr and it's data i.e. int a. Then contains the next base class's i.e. Base2 _vptr, then it's data (if any). Next, it's third base class i.e. Base3 class's _vptr and it's data.
Then at the end it contains it's own data i.e Derive class's data i.e. int b here the example.
In next artcile, I will talk about how Virtul Table and _vptr looks, in case of Diamnd Problem and it's solution in Multiple Inheritance.

