Yesterday the written test encountered a question about the size of the space occupied by the class, did not pay much attention before, come back to do a test, but also really found the problem, after the examination of the examiner door, when the question please specify what the compiler.
VC6/VC8 CL and Dev-c's g++ to do the test:
On the code,
Test code:
#include <stdio.h>
Class A
{
Public
int x;
int y;
A ()
{
x = 1;
y = 2;
};
void Go ()
{
printf ("A go () \ n");
}
virtual void Move ()
{
printf ("A Move () \ n");
}
};
Class B:virtual Public A
{
Public
int x;
int y;
B ()
{
x = 3;
y = 4;
}
void Go ()
{
printf ("B go () \ n");
}
virtual void Move ()
{
printf ("B Move () \ n");
}
virtual void Move2 ()
{
printf ("B Move2 () \ n");
}
};
Class C:public A
{
Public
int x;
int y;
C ()
{
x = 5;
y = 6;
}
/*
virtual void Move ()
{
printf ("C Move () \ n");
}
virtual void Move3 ()
{
printf ("C Move2 () \ n");
}
*/
};
Class D:virtual public c,virtual public B
{
};
void Printclass (void * Base,int size)
{
//print architecture
DWORD p, Pnext;
printf ("--------size=%d------------------\ n", size);
for (int i = 0;i<size/4;i++)
{
p = (DWORD) base+i* 4;
pnext = * (DWORD *) (p);
printf (" |--0x%08x : 0x%08x", P,pnext); //What's in the print class?
if (pnext>0x400000) //Print the contents of a contiguous three address under this address
{
printf (" : 0x%08x 0x%08x 0x%08x", * (DWORD *) pnext,* (DWORD *) (PNEXT+4), * (DWORD *) (PNEXT+8));
}
printf ("\ n");
}
printf (" |--end \ n \ nthe");
}
int main (int argc, char* argv[])
{
void * P1,*P2,*P3,*P4;
D DD; Because it inherits everything, so test it with it.
B * boy = ⅆ are all parent classes
C * Child = ⅆ
A * man = boy;
int sizea = sizeof (A);
int Sizeb = sizeof (B);
int Sizec = sizeof (C);
int sized = sizeof (D);
Translate into pointers
P1 = (void *) man;
P2 = (void *) boy;
P3 = (void *) child;
P4 = (void *) ⅆ
Printclass (P1,sizea);
Printclass (P2,sizeb);
Printclass (P3,sizec);
Printclass (p4,sized);
System ("pause");
return 0;
}
VC + + Results VC6 and VS2005 are the same as the previous picture a B C D size is 12 32 20 56
One more gcc. Result diagram a B C D is in the size of 12 24 20 48
Comparing the results of VC + + and g++ we will find
VC + + size is: 12 32 20 56
g++ Size: 12 24 20 48
The code is the same, but the results are different.
GCC in C + + is fully follow the C + + standard of VC + + as if not so pure pedigree, unexpected results
Analysis:
Look at the GCC diagram first.
look at A and C in comparison,
A is that the base class C is a subclass of direct inheritance
A There is a virtual function there must be a virtual function table pointer vfptr size is 4 bytes 0x00404420 is the virtual function table address
Plus two integer variables 4 + 41 A common size is 12 so size (A) = 12;
C inherits from a so the child members are inherited 4 + 4 plus virtual function table pointer (VFPTR) + 4 then add own two member variable 4 + 4
Altogether is 4+4+4+4+4 = 20;
Compare A and B,
B is the virtual inheritance of a that would have a virtual base class table pointer (vbptr) 0X40440C is the address
A = 12
B = 8 (two variable) +4 (vbptr) +a = 8 + 4 + 12 = 24;
And it's easy for us to understand
Compare A, B, C and D
When you see the structure of D, it is easy to see that D is such a structure d = [vbptr] + [C] +[b]
Because D inherits their existing variables and virtual function tables by inheriting them from B C.
So D = 4 + C + B = 4 +20 + 24 = 48
OK, g++ 's analysis is over, if you feel there is a mistake, please correct me.
In this sense, it is perfectly fine, so we can calculate the size of a class.
From the above image we can see their virtual function table and virtual base class table pointers will be as shared inheritance, do not know what I said is not right, I hope to get the expert guidance
Then look at VC + +
VC + + will make people very egg pain after all it comes out is the C + + standard as if it is not compatible, is completely Microsoft's that set bar (own guess)
Let's look at VC + + results 12 32 20 56 contrast g++ 's B and D are different
Well, take a closer look at B and D and find some weird questions.
You can see for yourself. No, it's not possible for me to do that, but the comparison between D and C, we can find something.
d= 4+ B + C In other words it is virtual inheritance but found that there is an address in the inside is 0x00000000, do not know what reason,
Be interested to analyze the reasons below. Although the results are the same for the final implementation.
Summary: It seems that GCC should be pure and the same as the book said, but VC + + seems to be a bit of a problem, not the book said, after the examiner's question or to GCC as the standard Ah, VC + + is a half tone ah
Finally, I added the test code to the test.
Man->move ();
Boy->move ();
Child->move ();
VC + + output results are:
B Move ()
B Move ()
C Move ()
The result of the GCC output is:
B Move ()
B Move ()
C Move ()
The output is the same, it means they get the same effect, but the data structure is different.
Interested students can study, here also reminds the major companies of the examiners, when the question to indicate what is the compiler or C + + standard.
Discussion on virtual inheriting memory object model of C + +
Recently, I have seen the memory layout of the objects in inside C + + which are virtual inheritance levels, and found that there are differences in different compiler implementations. So, I've explored it myself. The results are as follows:
First, talk about the GCC compiler.
It is relatively simple to implement, regardless of whether virtual inheritance,gcc is the virtual table pointer in the entire inheritance relationship is shared, does not share a pointer to the virtual base class .
Class A {
int A;
Virtual ~a () {}
};
Class B:virtual Public a{
Virtual ~b () {}
virtual void Myfunb () {}
};
Class C:virtual Public a{
Virtual ~c () {}
virtual void MyfunC () {}
};
Class D:public B,public c{
Virtual ~d () {}
virtual void Myfund () {}
};
In the code above, sizeof (A) =8,sizeof (B) =12,sizeof (C) =12,sizeof (D) =16.
Explanation: A medium Int+ virtual table pointer . B,c because it is virtual inheritance so the size of a + pointer to the virtual base class , B,c, although added its own virtual function, but the virtual table pointer is shared with the base class, so there will not be its own virtual table pointer . D because b,c are virtual inheritance, D contains only a copy of a, and d is equal to the pointer to the virtual base class in the pointer +c to the virtual base class in A+b.
If B,c is not a virtual inheritance, but an ordinary inheritance, then the size of the A,B,C is 8 (no pointers to the virtual base class), and D, because it is not a virtual inheritance, therefore contains two copies of a, size 16. Note that while the size of D is the same as virtual inheritance, the memory layout is different.
Then, take a look at the VC compiler
VC handles virtual table pointers more complex than GCC, which determines whether virtual table pointers are shared in an inheritance relationship based on virtual inheritance , while pointers to virtual base classes are not shared as well as GCC, and certainly not .
Code ibid.
The result will be sizeof (A) =8,sizeof (B) =16,sizeof (C) =16,sizeof (D) =24.
Explanation: A is still a int+ virtual table pointer . Because virtual table pointers are not shared in b,c because of their virtual functions, B,c maintains a virtual table pointer, which points to its own virtual function, respectively, because B,c joins its own imaginary function . ( Note: The compiler adds a virtual table pointer to a subclass only if the subclass has a new virtual function ) so the b,c size is a + own virtual table pointer + pointer to the virtual base class. D because b,c are virtual inheritance, D contains only a copy of a, while D is inherited from B,c, not virtual, and therefore does not have its own virtual table pointer. The D size is equal to the pointer to the virtual base class in the virtual table pointer +b in the +C pointer to the virtual base class in A+b's virtual table pointer +c .
Similarly, if you remove the virtual inheritance, the result will be the same as the GCC result, A,b,c is 8,d 16, because the VC compiler for non-virtual inheritance, the parent and child classes are shared virtual table pointers .
On the size of virtual inheritance classes, VC + + and g++ results are different