The memory layout and the vtable layout depend on your compiler. Using my gcc for instance, they look like this:
sizeof(int) == 4
sizeof(A) == 8
sizeof(B) == 8
sizeof(C) == 20
Note that sizeof(int) and the space needed for the vtable pointer can also vary from compiler to compiler and platform to platform. The reason why sizeof(C) == 20 and not 16 is that gcc gives it 8 bytes for the A subobject, 8 bytes for the B subobject and 4 bytes for its member int c
.
Vtable for C
C::_ZTV1C: 6u entries
0 (int (*)(...))0
4 (int (*)(...))(& _ZTI1C)
8 A::funA
12 (int (*)(...))-0x00000000000000008
16 (int (*)(...))(& _ZTI1C)
20 B::funB
Class C
size=20 align=4
base size=20 base align=4
C (0x40bd5e00) 0
vptr=((& C::_ZTV1C) + 8u)
A (0x40bd6080) 0
primary-for C (0x40bd5e00)
B (0x40bd60c0) 8
vptr=((& C::_ZTV1C) + 20u)
Using virtual inheritance
class C : public virtual A, public virtual B
the layout changes to
Vtable for C
C::_ZTV1C: 12u entries
0 16u
4 8u
8 (int (*)(...))0
12 (int (*)(...))(& _ZTI1C)
16 0u
20 (int (*)(...))-0x00000000000000008
24 (int (*)(...))(& _ZTI1C)
28 A::funA
32 0u
36 (int (*)(...))-0x00000000000000010
40 (int (*)(...))(& _ZTI1C)
44 B::funB
VTT for C
C::_ZTT1C: 3u entries
0 ((& C::_ZTV1C) + 16u)
4 ((& C::_ZTV1C) + 28u)
8 ((& C::_ZTV1C) + 44u)
Class C
size=24 align=4
base size=8 base align=4
C (0x40bd5e00) 0
vptridx=0u vptr=((& C::_ZTV1C) + 16u)
A (0x40bd6080) 8 virtual
vptridx=4u vbaseoffset=-0x0000000000000000c vptr=((& C::_ZTV1C) + 28u)
B (0x40bd60c0) 16 virtual
vptridx=8u vbaseoffset=-0x00000000000000010 vptr=((& C::_ZTV1C) + 44u)
Using gcc, you can add -fdump-class-hierarchy
to obtain this information.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…