C ++ 2.0 and later fully support virtual functions and virtual inheritance. The introduction of these two features has added many functions to C ++ and brought a lot of troubles. What are the features of virtual functions and virtual inheritance? I will not record them today. If you can understand how the compiler implements virtual functions and virtual inheritance, how they are laid out in the memory space of the class, but you can have a lot of in-depth understanding of C ++. It took some time to get to know these things, even though it was a bit rewarding.
First readCode
Class
{
Virtual AA (){};
};
Class B: Public Virtual A
{< br> char J [3]; // Add a variable to check the position of vfptr in the class.
Public:
virtual BB () {};
};
Class C: Public Virtual B
{< br> char I [3];
Public:
virtual CC (){};
};
I will not give the results this time. I will analyze the results first to enhance my impression.
1. for Class A, because there is only one virtual function, there must be a corresponding virtual function table to record the corresponding function entry address. In the memory space of Class A, A vfptr_a must point to the table. Sizeof (a) is also easy to determine, for 4.
2. for Class B, because Class B is based on class A, it also has its own virtual function. Therefore, Class B first has a vfptr_ B, pointing to its own virtual function table. In addition, char J [3] is used to perform an alignment operation. The general size is 4. How can virtual inheritance be implemented? This is Ah problem! I did not know it before, but I still have an introduction to the C ++ object model. First, you must add a virtual L class pointer (vbptr_ B _a) to point to its parent class, and then include all the content of the parent class. It's complicated, but it's not hard to imagine. Sizeof (B) = 4 + 4 + 4 + 4 = 16 (vfptr_ B, char J [3] for alignment, vbptr_ B _a, and Class ).
3. The next step is Class C. Class C should first have a vfptr_c, then Char I [3], then vbptr_c_ B, and then Class B, so sizeof (c) = 4 + 4 + 4 + 16 = 28 (vfptr_c, char I [3] for alignment, vbptr_c_a, and Class B ).
In VC 6.0, I wroteProgram, Print the size of the above classes, and the results are 4, 16, and 28. Hoho! Really done? After the above analysis, although the specific memory layout of each class is not clear, the content should not be wrong. Hey, that's exactly what I thought when I was not tracking, but the result was ......
Virtual inheritance memory layout in VC-single inheritance
I drew a picture to briefly show my tracking results.
Memory layout for single inheritance based on virtual Foundations
The case of Class A is too simple, no problem. The following conclusions can be drawn from the memory layout diagram of Class B.
1. vf_ptr B is placed in the Class header. It is very dangerous if you want to copy the class directly with memcpy, and it is impossible to use struct. Next day, let's take a deeper look at the differences between struct and class. We can see the differences here.
2. Why is vbtbl_ptr_ B not described previously? This pointer is very different from the content I have previously guessed. This Pointer Points to the virtual class table of Class B (well, the name I set up on my own is really not refined ). Look at VB table. There are two items in VB table. The first item is fffffffc. The value of this item may be meaningless. It may be to ensure that the virtual table is not empty. The second item is 8, which looks like the shift of Class A in Class B to this vbtbl_ptr_ B, that is, an offset. Similar methods are introduced in C ++ Object Model (p121). You can check them out.
The memory layout of class C is complicated, but its memory layout also further shows that my understanding of the content in vbtbl_ptr_ B, that is, the virtual table, is correct. However, it is worth noting that Class A in Class B is moved to the front during layout. Although the entire size has not changed, if such an operation is performed C; B * B; B = & C; how does B perform? In this case, you only need to obtain the position of Class B from the virtual class table in C, which can be assigned to B. However, the construction of class C is complicated, and the subsequent use is very simple and efficient. If the memory layout of Class A is moved forward, the virtual inheritance sequence of Class A may be considered.
Conclusion
1. VC puts vfptr in the Class header during compilation;
2. VC uses the virtual table pointer (vbtbl_ptr) to determine the virtual class inherited by a class.
3. VC will re-adjust the memory layout of the parent class of the virtual inheritance in the subclass. (The specific rules are unclear)
4. the first item in the virtual table in VC is meaningless, probably to ensure sizeof (virtual table )! = 0; the following content is the offset of the parent class in the subclass relative to the virtual class Table pointer.
at present, the memory layout of virtual inheritance in a single inheritance is clear, but what about multiple inheritance? This is too BT, and the simple multi-inheritance has not yet been clarified. It is more than just a virtual inheritance. If you are interested in it later, find it.