一个g++;编译器用虚函数实现多重继承? 在“C++对象模型内部”中提到,派生类具有 n 1 < /COD>额外的虚拟表,即 n>代码>是基类的数目。我用g++编译器做了一些实验,我的机器是64位的。 下面是我的代码 class A{ private: int a; public: virtual void print() const{ cout << a << endl; } }; class B : A{ private: int b; public: virtual void set(int num){ b = num; } }; class C : public A, public B{ private: int c; public: void print() const{ cout << c << endl; } void set(int num){ c = num; } };
然后,我对以下问题感到困惑一个g++;编译器用虚函数实现多重继承? 在“C++对象模型内部”中提到,派生类具有 n 1 < /COD>额外的虚拟表,即 n>代码>是基类的数目。我用g++编译器做了一些实验,我的机器是64位的。 下面是我的代码 class A{ private: int a; public: virtual void print() const{ cout << a << endl; } }; class B : A{ private: int b; public: virtual void set(int num){ b = num; } }; class C : public A, public B{ private: int c; public: void print() const{ cout << c << endl; } void set(int num){ c = num; } };,c++,C++,然后,我对以下问题感到困惑 甲级 尺寸=16对齐=8 底座尺寸=12底座对齐=8 我不明白为什么A级的大小是16,基本大小和对齐是什么意思?我认为类A的大小应该是12个字节,vptr为8个字节,intA为4个字节。B类也一样 我原以为C类有2个vtables,但结果显示只有一个有7个条目。这个vtable和C类的两个vptr之间有什么关系 最后一行显示vptr=(&C::ZTV1C)+48u),48是什么意思?C类的vtable的最后一个条目显示 48(int(*)(…)C::\uzthn1
甲级
尺寸=16对齐=8
底座尺寸=12底座对齐=8
我不明白为什么A级的大小是16,基本大小和对齐是什么意思?我认为类A的大小应该是12个字节,vptr
为8个字节,intA
为4个字节。B类也一样vtables
,但结果显示只有一个有7个条目。这个vtable
和C类的两个vptr
之间有什么关系vptr=(&C::ZTV1C)+48u)
,48是什么意思?C类的vtable
的最后一个条目显示
48(int(*)(…)C::\uzthn16\un1c3setei
这是什么意思?它不是虚拟函数的名称和到顶部的偏移量。为什么第二个vptr
指向此条目将对象指针强制转换为某些父类可能需要添加一些偏移量(以获得正确的vtable和member函数)。关于问题1,您需要查看结构填充。您的PC arch是16字节对齐的。int需要4个字节,print的函数指针需要8个字节,因此12个字节表示基本大小,最后4个字节用于数据对齐。()
(gdb) p a
$1 = (A) {
_vptr.A = 0x400bb0 <vtable for A+16>,
a = 0
}
(gdb) p b
$2 = (B) {
_vptr.B = 0x400b90 <vtable for B+16>,
b = 4196384
}
(gdb) p c
$3 = (C) {
<A> = {
_vptr.A = 0x400b50 <vtable for C+16>,
a = 4197101
},
<B> = {
_vptr.B = 0x400b70 <vtable for C+48>,
b = 0
},
members of C:
c = 0
}
Vtable for A
A::_ZTV1A: 3u entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI1A)
16 (int (*)(...))A::print
Class A
size=16 align=8
base size=12 base align=8
A (0x0x7fe4654956c0) 0
vptr=((& A::_ZTV1A) + 16u)
Vtable for B
B::_ZTV1B: 3u entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI1B)
16 (int (*)(...))B::set
Class B
size=16 align=8
base size=12 base align=8
B (0x0x7fe465495720) 0
vptr=((& B::_ZTV1B) + 16u)
Vtable for C
C::_ZTV1C: 7u entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI1C)
16 (int (*)(...))C::print
24 (int (*)(...))C::set
32 (int (*)(...))-16
40 (int (*)(...))(& _ZTI1C)
48 (int (*)(...))C::_ZThn16_N1C3setEi
Class C
size=32 align=8
base size=32 base align=8
C (0x0x7fe46516e690) 0
vptr=((& C::_ZTV1C) + 16u)
A (0x0x7fe465495780) 0
primary-for C (0x0x7fe46516e690)
B (0x0x7fe4654957e0) 16
vptr=((& C::_ZTV1C) + 48u)