Review the knowledge of C + + today, when see the virtual base class this time, there is no too much to investigate, is to know that the virtual base class is to eliminate the class inheritance between the two semantic problem, but is very curious, how it is eliminated, how the memory layout is distributed? So I studied it in depth, and the concrete principle is as follows:
In C + +, obj is a class object, p is a pointer to obj, which has a data member Mem, ask Obj.mem and p->mem in the implementation and efficiency is different.
The answer is: there is only one case where there are significant differences, which must meet the following 3 conditions:
(1), obj is an object of a virtual inherited derived class
(2), Mem is a member derived from the virtual base class
(3), p is a pointer to the base class type
In this case, the P->MEM will have two more layers than the obj.mem. (That is, in this case, P->MEM is significantly slower than OBJ.MEM)
WHY?
If your curiosity is heavier, look down:
1, the use of virtual base class, and the realization of the virtual function for polymorphism is different, is to solve the multiple inheritance of the two semantic problem.
Examples are as follows:
Class A
{public
:
int A;
};
Class B:virtual public A
{public
:
int B;
};
Class C:virtual public A
{public
:
int C;
};
Class D:public B, public C
{public
:
int D;
};
In the above diamond-like inheritance system, if there is no virtual inheritance, then there are two members of a in d that are int A; there is a lot of ambiguity when it comes to use. And with the virtual inheritance, in D only a copy of the member int A;, the copy is not from B, not from C, but a separate copy, then how does the compiler achieve it??
Before you answer this question, think about sizeof (A), sizeof (B), sizeof (C), sizeof (D). (Under the linux2.6 of 32-bit x86, or under vc2005) under linux2.6, the results are as follows: sizeof (A) = 4; sizeof (B) = 12; sizeof (C) = 12; sizeof (D) = 24;sizeof (B) Why is 12, that is because of a pointer (which is the same as the implementation of the virtual function), what is that pointer?
So sizeof (D) Why is 24? That is because, in addition to the c,a in the b,c in the inheritance B, a, and D own member D, also inherits the B,c more than 2 pointers (b and C respectively). Again, the int a in D is not from B or C, but is another member who comes directly from a.
If the object of D is declared D:D D;
Then the memory layout for D is as follows:
Vb_ptr: Pointers to inherit from B
int B: inherited from B Public members
Vc_ptr: Pointers inherited from C
int C: A shared member inherited from C
int D:D own Public member
int A: A public member inherited from a
So what happens to the following usage?
D DD;
B *PB = &dD;
pb->a;
As stated above, the int a in DD is not inherited from B, nor is it inherited from C, so how does the pb->a in this B know to point to the sixth item in DD memory?
That is the magical vb_ptr of the pointer. The principle is as follows: (in fact, the implementation of g++3.4.3 more complex, I do not know what to consider, and I only say the principle here, so the process and content to simplify)
First, the vb_ptr points to the address of an integer in which the integer is the displacement of the distance DD at the beginning of the int a (where vb_ptr points to the address where the 20 is in bytes). The compiler does this:
First of all, find vb_ptr (this do not find, because in the g++, Vb_ptr is the first in b*, hehe), and then get the content of the address of the vb_ptr point (this example is 20), and finally the content and the pointer PB added, you get the address of the pb->a.
So at this point, you can use the pointer to convert more than two middle layers to find the members of the base class, and it is the runtime.
It can also be inferred that the contents of vb_ptr and Vc_ptr in DD are the same, pointing to the same address, which is 20 (in this case)
Like the following statement:
This statement does not need to be converted, because the compiler knows during compilation that he inserted the member of a in the DD (in this case the end), so the efficiency of the statement is the same as the dd.a (at least the same)
This is the basic principle of the virtual base class implementation.
Note that the position of those pointers and the memory layout of the base class members in the derived class members are indeterminate, that is, there is no provision in the standard INTA must be put in the end, just g++ compiler implementation. C + + standard probably only stipulates the principle of this set of mechanisms, as for the specific implementation, such as the discharge of the members of the Order and optimization, by the various compiler manufacturers set their own ~
Non-Virtual inheritance:
In a derived class object, the base class object is distributed sequentially in the order of the inheritance Declaration, and finally the derived class data member.
Jocky class declares a virtual function, the base class object has a virtual function table pointer and then a base class data member.
In a base class virtual function table, the virtual function of the base class, in turn, is replaced with a function of a derived class if a function is override by a derived class.
A virtual function unique to a derived class is appended to the virtual function table of the first base class.
Virtual Inheritance:
In a derived class object, the Non-virtual base class object is distributed sequentially in the order of the inheritance Declaration, followed by the derived class data member, and finally the virtual base class object.
Jocky class declares a virtual function, the base class object has a virtual function table pointer and then a base class data member.
In a base class virtual function table, the virtual function of the base class, in turn, is replaced with a function of a derived class if a function is override by a derived class.
If a class that derives directly from a virtual base class does not have a non-virtual parent class, and a new virtual function is declared, the derived class has its own virtual function table in the derived class's head; otherwise, the virtual function unique to the derived class is appended to the virtual function table of the first Non-virtual base class.
The class that derives directly from the virtual base class also has a virtual base class table pointer (a hidden "virtual base class table pointer" member, pointing to a virtual base class table), after the non-virtual base class object (if any) before the data member.
The first value in the Virtual base class table is the offset from the virtual base class table to the starting address of the derived class; The value that follows is the address offset of the derived class's virtual base class to the table location (the offset between the address of the virtual base class object and the virtual base class table pointer of the derived class).
For virtual function table pointers and virtual base class table pointers:
When single inheritance is not virtual inheritance: Each table containing virtual functions has only one virtual function table, so only one virtual table pointer is required;
When multiple inheritance and not virtual inheritance: A subclass has several parent classes will have several virtual function table, so there is the same as the number of the parent class virtual table pointer to identify;
In summary, no additional virtual function table pointers are required when non-virtual inheritance is not needed.
When virtual inheritance: whether it is a single virtual inheritance or multiple virtual inheritance, a virtual base class table is needed to record the virtual inheritance relationship, so the subclass needs one more virtual base class table pointer, and only one can be needed.
When a virtual inheritance can hold multiple virtual function tables in a class: whether it is a single virtual inheritance or a multiple virtual inheritance,
If the subclass has no constructors and destructors, and the virtual function in the subclass is a virtual function that appears in the parent class, there is no need to add any virtual table pointers, just like multiple inheritance of the virtual table pointer holding the number of the parent class;
If a subclass contains constructors or destructors or both, then a virtual function table pointer should be added to identify the virtual function table of this class as long as the virtual function in a parent class appears in the subclass.
Whether or not it contains a constructor or a fictional function, as long as the inheritance is virtual inheritance and there is a virtual function that does not appear in the parent class, an additional function table pointer is needed in the subclass, and if one of them is a non-virtual inheritance, you do not need to add a virtual function table pointer according to the principle of the most provincial space. Because this time you can share a virtual function table pointer with the Non-virtual base class.
The above is a small series for you to discuss the virtual base class in C + + the memory layout in the derived class all the content, I hope that we support cloud Habitat Community ~