http://blog.csdn.net/haoel/article/details/3081385
memory layout for C + + objects (bottom)
Chenhao
Http://blog.csdn.net/haoel
<<< Click here to view the previous article Repeat Inheritance
Let's take another look at the case of duplicate inheritance. The so-called duplicate inheritance, that is, a base class is indirectly repeated inherited several times.
The following figure is an inheritance graph, and we overload the F () function of the parent class.
The source code that inherits from its class is shown below. Among them, each class has two variables, one is reshaping (4 bytes), one is the character (1 bytes), but also has its own virtual function, its own overwrite the virtual function of the parent class. As in Subclass D, F () overrides the superclass function, F1 () and F2 () cover the virtual function of its parent class, and Df () is its own virtual function.
Class B
{
Public
int IB;
Char CB;
Public
B (): IB (0), CB (' B ') {}
Virtualvoid f () {cout << "b::f ()" << Endl;}
Virtualvoid Bf () {cout << "B::BF ()" << Endl;}
};
Class B1:public B
{
Public
int IB1;
Char CB1;
Public
B1 (): IB1 (one), CB1 (' 1 ') {}
Virtualvoid f () {cout << "b1::f ()" << Endl;}
Virtualvoid F1 () {cout << "b1::f1 ()" << Endl;}
Virtualvoid Bf1 () {cout << "b1::bf1 ()" << Endl;}
};
Class B2:public B
{
Public
int ib2;
Char CB2;
Public
B2 (): Ib2 (), CB2 (' 2 ') {}
Virtualvoid f () {cout << "b2::f ()" << Endl;}
Virtualvoid F2 () {cout << "b2::f2 ()" << Endl;}
Virtualvoid Bf2 () {cout << "b2::bf2 ()" << Endl;}
};
Class D:public B1, public B2
{
Public
int id;
char cd;
Public
D (): ID (m), CD (' D ') {}
Virtualvoid f () {cout << "d::f ()" << Endl;}
Virtualvoid F1 () {cout << "d::f1 ()" << Endl;}
Virtualvoid F2 () {cout << "d::f2 ()" << Endl;}
Virtualvoid Df () {cout << "D::D F ()" << Endl;}
};
The code we use to access the child-class memory layout is shown below: (under VC + + 2003 and g++ 3.4.4)
Typedefvoid (*fun) (void);
int** pvtab = NULL;
Fun pfun = NULL;
D D;
Pvtab = (int**) &d;
cout << "[0] d::b1::_vptr->" << Endl;
Pfun = (Fun) pvtab[0][0];
cout << "[0]"; Pfun ();
Pfun = (Fun) pvtab[0][1];
cout << "[1]"; Pfun ();
Pfun = (Fun) pvtab[0][2];
cout << "[2]"; Pfun ();
Pfun = (Fun) pvtab[0][3];
cout << "[3]"; Pfun ();
Pfun = (Fun) pvtab[0][4];
cout << "[4]"; Pfun ();
Pfun = (Fun) pvtab[0][5];
cout << "[5] 0x" << pfun << Endl;
cout << "[1] b::ib =" << (int) pvtab[1] << Endl;
cout << "[2] B::CB =" << (char) pvtab[2] << Endl;
cout << "[3] b1::ib1 =" << (int) pvtab[3] << Endl;
cout << "[4] B1::CB1 =" << (char) pvtab[4] << Endl;
cout << "[5] d::b2::_vptr->" << Endl;
Pfun = (Fun) pvtab[5][0];
cout << "[0]"; Pfun ();
Pfun = (Fun) pvtab[5][1];
cout << "[1]"; Pfun ();
Pfun = (Fun) pvtab[5][2];
cout << "[2]"; Pfun ();
Pfun = (Fun) pvtab[5][3];
cout << "[3]"; Pfun ();
Pfun = (Fun) pvtab[5][4];
cout << "[4] 0x" << pfun << Endl;
cout << "[6] B::ib =" << (int) pvtab[6] << Endl;
cout << "[7] B::CB =" << (char) pvtab[7] << Endl;
cout << "[8] b2::ib2 =" << (int) pvtab[8] << Endl;
cout << "[9] b2::cb2 =" << (char) pvtab[9] << Endl;
cout << "[ten] D::id =" << (int) pvtab[10] << Endl;
cout << "[one] d::cd =" << (char) pvtab[11] << Endl;
The results of the program operation are as follows:
GCC 3.4.4 |
VC + + 2003 |
[0] d::b1::_vptr-> [0] D::f () [1] B::BF () [2] d::f1 () [3] B1::bf1 () [4] D::F2 () [5] 0x1 [1] b::ib = 0 [2] b::cb = B [3] b1::ib1 = One [4] B1::CB1 = 1 [5] d::b2::_vptr-> [0] D::f () [1] B::BF () [2] d::f2 () [3] B2::BF2 () [4] 0x0 [6] b::ib = 0 [7] B::CB = B [8] b2::ib2 = [9] b2::cb2 = 2 [A] D::id = [one] d::cd = D |
[0] d::b1::_vptr-> [0] D::f () [1] B::BF () [2] d::f1 () [3] B1::bf1 () [4] D::D f () [5] 0x00000000 [1] b::ib = 0 [2] b::cb = B [3] b1::ib1 = One [4] B1::CB1 = 1 [5] d::b2::_vptr-> [0] D::f () [1] B::BF () [2] d::f2 () [3] B2::BF2 () [4] 0x00000000 [6] b::ib = 0 [7] B::CB = B [8] b2::ib2 = [9] b2::cb2 = 2 [A] D::id = [one] d::cd = D |
The following is a diagram of a virtual function table in a subclass instance:
We can see that the topmost parent class B has its member variables in B1 and B2 and is inherited by D. And in D, there are instances of B1 and B2, so the members of B have two in the case of D, one in B1 succession and the other in B2 inheritance. So, if we use the following statement, we will produce a ambiguity compilation error:
D D;
D.ib = 0; Ambiguity error
D.b1::ib = 1; That's right
D.b2::ib = 2; That's right
Note that the last two statements in the preceding routine access two variables. Although we eliminated the two semantic compilation errors, the B class had two instances in D, which resulted in duplication of data, which we call inheriting as duplicate inheritance. Duplicate base class data members may not be what we want. Therefore, C + + introduces the concept of virtual base class. multi-Virtual inheritance of diamond type
The emergence of virtual inheritance is to solve the problem of multiple indirect parent classes in duplicate inheritance. The diamond type structure is its most classic structure. And the structure we're going to discuss here:
The above "repeat inheritance" only needs to add the virtual key to the syntax of B1 and B2 inheritance B, and the inheritance diagram below is as follows:
The internal data and interfaces of the classes in the above and previous "repeat inheritance" are exactly the same, but we use virtual inheritance: The omitted source code looks like this:
Class B {...};
Class B1: virtualpublic b{...};
Class B2: virtualpublic b{...};
Class D:public B1, public b2{...};
Before looking at D, let's take a look at the case of a single virtual inheritance . Below is a section of the test program under vc++2003: (because VC + + and GCC memory and the bureau has some details on the difference, so here only give the VC + + program, GCC under the program you can according to the program I gave you to write a to try it):
int** pvtab = NULL;
Fun pfun = NULL;
B1 BB1;
Pvtab = (int**) &bb1;
cout << "[0] b1::_vptr->" << Endl;
Pfun = (Fun) pvtab[0][0];
cout << "[0]";
Pfun (); B1::F1 ();
cout << "[1]";
Pfun = (Fun) pvtab[0][1];
Pfun (); B1::bf1 ();
cout << "[2]";
cout << pvtab[0][2] << Endl;
cout << "[1] = 0x";
cout << (int*) * ((int*) (&BB1) +1) <<endl; B1::ib1
cout << "[2] b1::ib1 =";
cout << (<