body, table{font-family: 微软雅黑; font-size: 10pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}
VS 调试查看内存布局:
(选中项目右键——》调试——》属性——》C/C++——》命令行——》其他——》/d1reportSingleClassLayoutB(最后一个B代表代码中的B类)——》解决方案资源管理器选中右键重新生成
(结合源码进行测试)
// 测试一:单个虚继承,不带虚函数
// 虚继承与继承的区别
// 1.多了一个虚基指针
// 2.虚基类位于派生类存储空间的最末尾
// 测试二:单个虚继承,带虚函数
// 1.如果派生类没有自己的虚函数,此时派生类对象不会产生
// 虚函数指针,有和基类一样的虚函数也不会产生虚函数指针
// 2.如果派生类拥有自己的虚函数,此时派生类对象就会产生自己本身的虚函数指针,
// 并且该虚函数指针位于派生类对象存储空间的开始位置
//单个继承,不带虚函数
1> class A size(4): 1> +--- 1> 0 | _ia 1> +--- |
1> class B size(8): 1> +--- //如果B类自己有虚函数,和下同 1> | +--- (base class A) 1> 0 | | _ia 1> | +--- 1> 4 | _ib |
class A { public: A() : _ia(10){} void f() { cout << "A::f()" << endl; } private: int _ia; }; |
class B : public A { public: B() : _ib(20){} void f() { cout << "B::f()" << endl; } void fb() { cout << "B::fb()" << endl; } void fb2() { cout << "B::fb2()" << endl; } private: int _ib; }; |
//单个继承,带虚函数
1> class A size(8): 1> +--- 1> 0 | {vfptr} //虚函数指针->虚函数表 1> 4 | _ia 1> +--- |
1> class B size(12): 1> +--- 1> | +--- (base class A) 1> 0 | | {vfptr} (A中的虚函数被覆盖) 1> 4 | | _ia 1> | +--- 1> 8 | _ib 1> +--- |
class A { public: A() : _ia(10){} virtual void f() { cout << "A::f()" << endl; } private: int _ia; }; |
class B : public A { public: B() : _ib(20){} virtual void f() { cout << "B::f()" << endl; } virtual void fb2() { cout << "B::fb2()" << endl; } void fb() { cout << "B::fb()" << endl; } private: int _ib; }; |
1> A::[email protected]: 1> | &A_meta 1> | 0 1> 0 | &A::f |
1> B::[email protected]: 1> | &B_meta 1> | 0 1> 0 | &B::f 1> 1 | &B::fb2 |
// 类B没有虚函数 1> class B size(12): 1> +--- 1> | +--- (base class A) 1> 0 | | {vfptr} 1> 4 | | _ia 1> | +--- 1> 8 | _ib 1> +--- |
1> B::[email protected]: 1> | &B_meta 1> | 0 1> 0 | &A::f |
1> class A size(8): 1> +--- 1> 0 | {vfptr} 1> 4 | _ia 1> +--- |
1> class B size(24): 1> +--- 1> 0 | {vfptr} //这里只会存自己类独有的虚函数 1> 4 | {vbptr} //虚基指针->虚基表 1> 8 | _ib 1> +--- 1> 12 | (vtordisp for vbase A) 1> +--- (virtual base A) 1> 16 | {vfptr} //A中的f被覆盖,存放的是B的f() 1> 20 | _ia |
//类A同上;B没有 virtual void fb2()和f() 1> class B size(16): 1> +--- 1> 0 | {vbptr} 1> 4 | _ib 1> +--- 1> +--- (virtual base A) 1> 8 | {vfptr} 1> 12 | _ia 1> +--- |
class B : virtual public A { public: B() : _ib(20){} virtual void f() { cout << "B::f()" << endl; } void fb() { cout << "B::fb()" << endl; } virtual void fb2() { cout << "B::fb2()" << endl; } private: int _ib; }; |
1> A::[email protected]: 1> | &A_meta 1> | 0 1> 0 | &A::f |
1> B::[email protected]@: 1> | &B_meta 1> | 0 1> 0 | &B::fb2 1> 1> B::[email protected]: 1> 0 | -4 1> 1 | 12 (Bd(B+4)A) 1> 1> B::[email protected]@: 1> | -16 1> 0 | &(vtordisp) B::f 1> 1> B::f this adjustor: 16 1> B::f2 this adjustor: 0 |
1> B::[email protected]: 1> 0 | 0 1> 1 | 8 (Bd(B+0)A) 1> 1> B::[email protected]: 1> | -8 1> 0 | &A::f |
正常单个继承内存布局基类在前;基类有虚函数最开头有虚函数指针;继承过来可能产生覆盖。虚继承,基类在内存布局的后面,布局开头是虚基指针,如果派生类有自己独有的虚函数,那么还会有一个虚函数指针,指向存放自己独有的虚函数的表,下面的基类会多一个4字节字段存放vtordisp,并且基类中和派生类重复的虚函数会被覆盖。 正常多个继承,和单一一样,每个基类的虚函数指针都继承过来,如果有产生覆盖(派生类和多个基类中都有同样的虚函数),则第一个基函数表存放覆盖的函数地址,和派生类特有的虚函数,后面的基类布局如果有和第一个基类一样的虚函数且产生覆盖,只会存放偏移量指向第一个基类覆盖的虚函数地址 |
//类A同上;B没有 virtual void fb2()
1> class B size(20): 1> +--- 1> 0 | {vbptr} 1> 4 | _ib 1> +--- 1> 8 | (vtordisp for vbase A) 1> +--- (virtual base A) 1> 12 | {vfptr} 1> 16 | _ia 1> +--- |
1> B::[email protected]: 1> 0 | 0 1> 1 | 12 (Bd(B+0)A) 1> 1> B::[email protected]: 1> | -12 1> 0 | &(vtordisp) B::f 1> 1> B::f this adjustor: 12 |
vtordisp for vbase A: 虚继承中派生类重写了基类的虚函数,并且在构造函数或者析构函数中使用指向基类的指针调用了该函数,编译器会为虚基类添加vtordisp域。
上述示例代码便会产生vtordisp字段!条件是。 1. 派生类重写了虚基类的虚函数。 2. 派生类定义了构造函数或者析构函数。 它所解决的问题是:由于对类的虚拟基的置换与对其派生类的置换之间有差异,可能会向虚函数传递错误的 this 指针。 该解决方案向类的各个虚拟基提供称作 vtordisp 字段的单个构造置换调整。 预编译命令关闭vtordisp字段的产生。 *只有在你确信所有类的构造函数或析构函数都虚拟地调用了虚拟函数,vtordisp才可以关掉。 #pragma vtordisp({on|off}) |
// 测试三:多重继承(带虚函数)
// 1. 每个基类都有自己的虚函数表
// 2. 派生类如果有自己的虚函数,会被加入到第一个虚函数表之中
// 3. 内存布局中, 其基类的布局按照基类被声明时的顺序进行排列
// 4. 派生类会覆盖基类的虚函数,只有第一个虚函数表中存放的是真实的被覆盖的函数的地址;其它的虚函数表中存放的并不是真实的对应的虚函数的地址,而只是一条跳转指令
class Base1 { public: Base1() : _iBase1(10){} virtual void f() { cout << "Base1::f()" << endl; } virtual void g() { cout << "Base1::g()" << endl; } virtual void h() { cout << "Base1::h()" << endl; } private: int _iBase1; }; |
class Base2 { public: Base2() : _iBase2(100){} virtual void f() { cout << "Base2::f()" << endl; } virtual void g() { cout << "Base2::g()" << endl; } virtual void h() { cout << "Base2::h()" << endl; } private: int _iBase2; }; |
class Base3 { public: Base3() : _iBase3(1000){} virtual void f() { cout << "Base3::f()" << endl; } virtual void g() { cout << "Base3::g()" << endl; } virtual void h() { cout << "Base3::h()" << endl; } private: int _iBase3; }; |
class Derived :public Base1,public Base2,public Base3 { public: Derived() : _iDerived(10000){} void f() { cout << "Derived::f()" << endl; } virtual void g1() // 会放到Base1的虚函数表 { cout << "Derived::g1()" << endl; } private: int _iDerived; }; |
1> class Base1 size(8): 1> +--- 1> 0 | {vfptr} 1> 4 | _iBase1 1> +--- |
1> class Base2 size(8): 1> +--- 1> 0 | {vfptr} 1> 4 | _iBase2 1> +--- |
1> class Base3 size(8): 1> +--- 1> 0 | {vfptr} 1> 4 | _iBase3 1> +--- |
1> class Derived size(28): 1> +--- 1> | +--- (base class Base1) 1> 0 | | {vfptr} 1> 4 | | _iBase1 1> | +--- 1> | +--- (base class Base2) 1> 8 | | {vfptr} 1> 12 | | _iBase2 1> | +--- 1> | +--- (base class Base3) 1> 16 | | {vfptr} 1> 20 | | _iBase3 1> | +--- 1> 24 | _iDerived 1> +--- |
1> Base1::[email protected]: 1> | &Base1_meta 1> | 0 1> 0 | &Base1::f 1> 1 | &Base1::g 1> 2 | &Base1::h 1> 1> Base1::f this adjustor: 0 1> Base1::g this adjustor: 0 1> Base1::h this adjustor: 0 |
1> Base2::[email protected]: 1> | &Base2_meta 1> | 0 1> 0 | &Base2::f 1> 1 | &Base2::g 1> 2 | &Base2::h 1> 1> Base2::f this adjustor: 0 1> Base2::g this adjustor: 0 1> Base2::h this adjustor: 0 |
1> Base3::[email protected]: 1> | &Base3_meta 1> | 0 1> 0 | &Base3::f 1> 1 | &Base3::g 1> 2 | &Base3::h 1> 1> Base3::f this adjustor: 0 1> Base3::g this adjustor: 0 1> Base3::h this adjustor: 0 |
1> Derived::[email protected]@: 1> | &Derived_meta 1> | 0 1> 0 | &Derived::f 1> 1 | &Base1::g 1> 2 | &Base1::h 1> 3 | &Derived::g1 1> 1> Derived::[email protected]@: 1> | -8 1> 0 | &thunk: this-=8; goto Derived::f 1> 1 | &Base2::g 1> 2 | &Base2::h 1> 1> Derived::[email protected]@: 1> | -16 1> 0 | &thunk: this-=16; goto Derived::f 1> 1 | &Base3::g 1> 2 | &Base3::h 1> 1> Derived::f this adjustor: 0 1> Derived::g1 this adjustor: 0 |
难点 class Derived :virtual public Base1, virtual public Base2, virtual public Base3 { public: Derived() : _iDerived(10000){} void f() { cout << "Derived::f()" << endl; } virtual void g1() { cout << "Derived::g1()" << endl; } private: int _iDerived; }; |
1> class Derived size(48): 1> +--- 1> 0 | {vfptr} //存放g1() 1> 4 | {vbptr} 1> 8 | _iDerived 1> +--- 1> 12 | (vtordisp for vbase Base1) 1> +--- (virtual base Base1) 1> 16 | {vfptr} 1> 20 | _iBase1 1> +--- 1> 24 | (vtordisp for vbase Base2) 1> +--- (virtual base Base2) 1> 28 | {vfptr} 1> 32 | _iBase2 1> +--- 1> 36 | (vtordisp for vbase Base3) 1> +--- (virtual base Base3) 1> 40 | {vfptr} 1> 44 | _iBase3 1> +--- |
class Derived :virtual public Base1, virtual public Base2, virtual public Base3 { public: Derived() : _iDerived(10000){} void f() { cout << "Derived::f()" << endl; } /*virtual*/ void g1() { cout << "Derived::g1()" << endl; } private: int _iDerived; }; |
1> class Derived size(44): 1> +--- 1> 0 | {vbptr} 1> 4 | _iDerived 1> +--- 1> 8 | (vtordisp for vbase Base1) 1> +--- (virtual base Base1) 1> 12 | {vfptr} 1> 16 | _iBase1 1> +--- 1> 20 | (vtordisp for vbase Base2) 1> +--- (virtual base Base2) 1> 24 | {vfptr} 1> 28 | _iBase2 1> +--- 1> 32 | (vtordisp for vbase Base3) 1> +--- (virtual base Base3) 1> 36 | {vfptr} 1> 40 | _iBase3 1> +--- |
1> Derived::[email protected]@: 1> | &Derived_meta 1> | 0 1> 0 | &Derived::g1 1> 1> Derived::[email protected]: 1> 0 | -4 1> 1 | 12 (Derivedd(Derived+4)Base1) 1> 2 | 24 (Derivedd(Derived+4)Base2) 1> 3 | 36 (Derivedd(Derived+4)Base3) 1> 1> Derived::[email protected]@: 1> | -16 1> 0 | &(vtordisp) Derived::f 1> 1 | &Base1::g 1> 2 | &Base1::h 1> 1> Derived::[email protected]@: 1> | -28 1> 0 | &(vtordisp) thunk: this-=12; goto Derived::f 1> 1 | &Base2::g 1> 2 | &Base2::h 1> 1> Derived::[email protected]@: 1> | -40 1> 0 | &(vtordisp) thunk: this-=24; goto Derived::f 1> 1 | &Base3::g 1> 2 | &Base3::h |
1> Derived::[email protected]: 1> 0 | 0 1> 1 | 12 (Derivedd(Derived+0)Base1) 1> 2 | 24 (Derivedd(Derived+0)Base2) 1> 3 | 36 (Derivedd(Derived+0)Base3) 1> 1> Derived::[email protected]@: 1> | -12 1> 0 | &(vtordisp) Derived::f 1> 1 | &Base1::g 1> 2 | &Base1::h 1> 1> Derived::[email protected]@: 1> | -24 1> 0 | &(vtordisp) thunk: this-=12; goto Derived::f 1> 1 | &Base2::g 1> 2 | &Base2::h 1> 1> Derived::[email protected]@: 1> | -36 1> 0 | &(vtordisp) thunk: this-=24; goto Derived::f 1> 1 | &Base3::g 1> 2 | &Base3::h |
1> class Derived size(28):
1> +---
1> | +--- (base class Base1)
1> 0 | | {vfptr}
1> 4 | | _iBase1
1> | +---
1> | +--- (base class Base2)
1> 8 | | {vfptr}
1> 12 | | _iBase2
1> | +---
1> | +--- (base class Base3)
1> 16 | | {vfptr}
1> 20 | | _iBase3
1> | +---
1> 24 | _iDerived
1> +---
1> Derived::[email protected]@:
1> | &Derived_meta
1> | 0
1> 0 | &Derived::f
1> 1 | &Base1::g
1> 2 | &Base1::h
1> 3 | &Derived::g1
1> Derived::[email protected]@:
1> | -8
1> 0 | &thunk: this-=8; goto Derived::f
1> 1 | &Base2::g
1> 2 | &Base2::h
1> Derived::[email protected]@:
1> | -16
1> 0 | &thunk: this-=16; goto Derived::f
1> 1 | &Base3::g
1> 2 | &Base3::h
B1: 4+4 =8 B2: 4+4 =8 B3: 4+4 =8 D:B1,B2,B3: 8+8+8+4=28 |
// 测试四:
虚基类没有采用虚继承
class B { public: B() : _ib(10), _cb('B'){} virtual void f() { cout << "B::f()" << endl; } virtual void Bf() { cout << "B::Bf()" << endl; } private: int _ib; char _cb; }; |
class B1 : public B { public: B1() : _ib1(100), _cb1('1'){} virtual void f() { cout << "B1::f()" << endl; } virtual void f1() { cout << "B1::f1()" << endl; } virtual void Bf1() { cout << "B1::Bf()" << endl; } private: int _ib1; char _cb1; }; |
class B2 : public B { public: B2() : _ib2(1000), _cb2('2'){} virtual void f() { cout << "B2::f()" << endl; } virtual void f2() { cout << "B2::f2()" << endl; } virtual void Bf2() { cout << "B2::Bf2()" << endl; } private: int _ib2; char _cb2; }; |
class D : public B1, public B2 { public: D() : _id(10000), _cd('3'){} virtual void f() { cout << "D::f()" << endl; } virtual void f1() { cout << "D::f1()" << endl; } virtual void f2() { cout << "D::f2()" << endl; } virtual void Df() { cout << "D::Df()" << endl; } private: int _id; char _cd; }; 重点 |
1> class B size(12): 1> +--- 1> 0 | {vfptr} 1> 4 | _ib 1> 8 | _cb 1> | <alignment member> (size=3) //这里表示内存对齐数量 1> +--- 1> B::[email protected]: 1> | &B_meta 1> | 0 1> 0 | &B::f 1> 1 | &B::Bf 1> 1> B::f this adjustor: 0 1> B::Bf this adjustor: 0 |
1> class B1 size(20): 1> +--- 1> | +--- (base class B) 1> 0 | | {vfptr} 1> 4 | | _ib 1> 8 | | _cb 1> | | <alignment member> (size=3) 1> | +--- 1> 12 | _ib1 1> 16 | _cb1 1> | <alignment member> (size=3) 1> +--- 1> B1::[email protected]: 1> | &B1_meta 1> | 0 1> 0 | &B1::f 1> 1 | &B::Bf 1> 2 | &B1::f1 1> 3 | &B1::Bf1 1> 1> B1::f this adjustor: 0 1> B1::f1 this adjustor: 0 1> B1::Bf1 this adjustor: 0 |
1> class B2 size(20): 1> +--- 1> | +--- (base class B) 1> 0 | | {vfptr} 1> 4 | | _ib 1> 8 | | _cb 1> | | <alignment member> (size=3) 1> | +--- 1> 12 | _ib2 1> 16 | _cb2 1> | <alignment member> (size=3) 1> +--- 1> B2::[email protected]: 1> | &B2_meta 1> | 0 1> 0 | &B2::f 1> 1 | &B::Bf 1> 2 | &B2::f2 1> 3 | &B2::Bf2 1> 1> B2::f this adjustor: 0 1> B2::f2 this adjustor: 0 1> B2::Bf2 this adjustor: 0 |
1> class D size(48): 1> +--- 1> | +--- (base class B1) 1> | | +--- (base class B) 1> 0 | | | {vfptr} 1> 4 | | | _ib 1> 8 | | | _cb 1> | | | <alignment member> (size=3) 1> | | +--- 1> 12 | | _ib1 1> 16 | | _cb1 1> | | <alignment member> (size=3) 1> | +--- 1> | +--- (base class B2) 1> | | +--- (base class B) 1> 20 | | | {vfptr} 1> 24 | | | _ib 1> 28 | | | _cb 1> | | | <alignment member> (size=3) 1> | | +--- 1> 32 | | _ib2 1> 36 | | _cb2 1> | | <alignment member> (size=3) 1> | +--- 1> 40 | _id 1> 44 | _cd 1> | <alignment member> (size=3) 1> +--- 1> D::[email protected]@: 1> | &D_meta 1> | 0 1> 0 | &D::f 1> 1 | &B::Bf 1> 2 | &D::f1 1> 3 | &B1::Bf1 1> 4 | &D::Df 1> D::[email protected]@: 1> | -20 1> 0 | &thunk: this-=20; goto D::f 1> 1 | &B::Bf 1> 2 | &D::f2 1> 3 | &B2::Bf2 1> 1> D::f this adjustor: 0 1> D::f1 this adjustor: 0 1> D::f2 this adjustor: 20 1> D::Df this adjustor: 0 |
1> class D size(48):
1> +---
1> | +--- (base class B1)
1> | | +--- (base class B)
1> 0 | | | {vfptr}
1> 4 | | | _ib
1> 8 | | | _cb
1> | | | <alignment member> (size=3)
1> | | +---
1> 12 | | _ib1
1> 16 | | _cb1
1> | | <alignment member> (size=3)
1> | +---
1> | +--- (base class B2)
1> | | +--- (base class B)
1> 20 | | | {vfptr}
1> 24 | | | _ib
1> 28 | | | _cb
1> | | | <alignment member> (size=3)
1> | | +---
1> 32 | | _ib2
1> 36 | | _cb2
1> | | <alignment member> (size=3)
1> | +---
1> 40 | _id
1> 44 | _cd
1> | <alignment member> (size=3)
1> +---
B: 4+4+1 =9 --->12 B1:B: 4+4+1 + 4+1 =14--->16 B2:B: 4+4+1 + 4+1 =14--->16 D:B1,B2: 12+16+16+4+1 =45--->48 |
//采用虚继承
//虚基指针所指向的虚基表的内容:
//1. 虚基指针的第一条内容表示的是该虚基指针距离所在的子对象的首地址的偏移
//2. 虚基指针的第二条内容表示的是该虚基指针距离虚基类子对象的首地址的偏移
class B { public: B() : _ib(10), _cb('B'){} virtual void f() { cout << "B::f()" << endl; } virtual void Bf() { cout << "B::Bf()" << endl; } private: int _ib; char _cb; }; |
class B1 : virtual public B { public: B1() : _ib1(100), _cb1('1'){} virtual void f() { cout << "B1::f()" << endl; } virtual void f1() { cout << "B1::f1()" << endl; } virtual void Bf1() { cout << "B1::Bf1()" << endl; } private: int _ib1; char _cb1; }; |
class B2 : virtual public B { public: B2() : _ib2(1000), _cb2('2'){} virtual void f() { cout << "B2::f()" << endl; } virtual void f2() { cout << "B2::f2()" << endl; } virtual void Bf2() { cout << "B2::Bf2()" << endl; } private: int _ib2; char _cb2; }; |
class D : public B1, public B2 { public: D() : _id(10000), _cd('3'){} virtual void f() { cout << "D::f()" << endl; } virtual void f1() { cout << "D::f1()" << endl; } virtual void f2() { cout << "D::f2()" << endl; } virtual void Df() { cout << "D::Df()" << endl; } private: int _id; char _cd; }; |
1> class B size(12): 1> +--- 1> 0 | {vfptr} 1> 4 | _ib 1> 8 | _cb 1> | <alignment member> (size=3) 1> +--- 1> 1> B::[email protected]: 1> | &B_meta 1> | 0 1> 0 | &B::f 1> 1 | &B::Bf 1> 1> B::f this adjustor: 0 1> B::Bf this adjustor: 0 |
1> class B1 size(32): 1> +--- 1> 0 | {vfptr} 1> 4 | {vbptr} 1> 8 | _ib1 1> 12 | _cb1 1> | <alignment member> (size=3) 1> +--- 1> 16 | (vtordisp for vbase B) 1> +--- (virtual base B) 1> 20 | {vfptr} 1> 24 | _ib 1> 28 | _cb 1> | <alignment member> (size=3) 1> +--- 1> 1> B1::[email protected]@: 1> | &B1_meta 1> | 0 1> 0 | &B1::f1 1> 1 | &B1::Bf1 1> 1> B1::[email protected]: 1> 0 | -4 1> 1 | 16 (B1d(B1+4)B) 1> 1> B1::[email protected]@: 1> | -20 1> 0 | &(vtordisp) B1::f 1> 1 | &B::Bf 1> 1> B1::f this adjustor: 20 1> B1::f1 this adjustor: 0 1> B1::Bf1 this adjustor: 0 |
1> class B2 size(32): 1> +--- 1> 0 | {vfptr} 1> 4 | {vbptr} 1> 8 | _ib2 1> 12 | _cb2 1> | <alignment member> (size=3) 1> +--- 1> 16 | (vtordisp for vbase B) 1> +--- (virtual base B) 1> 20 | {vfptr} 1> 24 | _ib 1> 28 | _cb 1> | <alignment member> (size=3) 1> +--- 1> 1> B2::[email protected]@: 1> | &B2_meta 1> | 0 1> 0 | &B2::f2 1> 1 | &B2::Bf2 1> 1> B2::[email protected]: 1> 0 | -4 1> 1 | 16 (B2d(B2+4)B) 1> 1> B2::[email protected]@: 1> | -20 1> 0 | &(vtordisp) B2::f 1> 1 | &B::Bf 1> 1> B2::f this adjustor: 20 1> B2::f2 this adjustor: 0 1> B2::Bf2 this adjustor: 0 |
1> class D size(56): 1> +--- 1> | +--- (base class B1) 1> 0 | | {vfptr} 1> 4 | | {vbptr} 1> 8 | | _ib1 1> 12 | | _cb1 1> | | <alignment member> (size=3) 1> | +--- 1> | +--- (base class B2) 1> 16 | | {vfptr} 1> 20 | | {vbptr} 1> 24 | | _ib2 1> 28 | | _cb2 1> | | <alignment member> (size=3) 1> | +--- 1> 32 | _id 1> 36 | _cd 1> | <alignment member> (size=3) 1> +--- 1> 40 | (vtordisp for vbase B) 1> +--- (virtual base B) 1> 44 | {vfptr} 1> 48 | _ib 1> 52 | _cb 1> | <alignment member> (size=3) 1> +--- 1> 1> D::[email protected]@: 1> | &D_meta 1> | 0 1> 0 | &D::f1 1> 1 | &B1::Bf1 1> 2 | &D::Df 1> 1> D::[email protected]@: 1> | -16 1> 0 | &D::f2 1> 1 | &B2::Bf2 1> 1> D::[email protected]@: 1> 0 | -4 1> 1 | 40 (Dd(B1+4)B) 1> 1> D::[email protected]@: 1> 0 | -4 1> 1 | 24 (Dd(B2+4)B) 1> 1> D::[email protected]@: 1> | -44 1> 0 | &(vtordisp) D::f 1> 1 | &B::Bf 1> 1> D::f this adjustor: 44 1> D::f1 this adjustor: 0 1> D::f2 this adjustor: 16 1> D::Df this adjustor: 0 |
1> class D size(52):
1> +---
1> | +--- (base class B1)
1> 0 | | {vfptr}
1> 4 | | {vbptr}
1> 8 | | _ib1
1> 12 | | _cb1
1> | | <alignment member> (size=3)
1> | +---
1> | +--- (base class B2)
1> 16 | | {vfptr}
1> 20 | | {vbptr}
1> 24 | | _ib2
1> 28 | | _cb2
1> | | <alignment member> (size=3)
1> | +---
1> 32 | _id
1> 36 | _cd
1> | <alignment member> (size=3)
1> +---
1> +--- (virtual base B)
1> 40 | {vfptr}
1> 44 | _ib
1> 48 | _cb
1> | <alignment member> (size=3)
1> +---
B : 4+1+4 =9 4+4+1=9--->12 B1:v B : 4+1+4+4+4+4+1 =22 4+4+4+1=13--->16 B2:v B : 4+1+4+4+4+4+1 =22 4+4+4+1=13--->16 D:B1,B2 : 12+16+16=44 +4+1 =49--->13*4=52 |
1> D::[email protected]@:
1> | &D_meta
1> | 0
1> 0 | &D::f1
1> 1 | &B1::Bf1
1> 2 | &D::Df
1> D::[email protected]@:
1> | -16
1> 0 | &D::f2
1> 1 | &B2::Bf2
1>
1> D::[email protected]@:
1> 0 | -4
1> 1 | 36 (Dd(B1+4)B)
1> D::[email protected]@:
1> 0 | -4
1> 1 | 20 (Dd(B2+4)B)
[原理最清晰] http://blog.csdn.net/jinri1234/article/details/5702011 http://blog.csdn.net/haoel/article/details/3081328 http://blog.csdn.net/haoel/article/details/3081385 [虚函数表里边保存的不一定是虚函数的地址] http://www.cnblogs.com/cswuyg/archive/2010/08/20/1804716.html [C++对象内存布局测试总结] http://www.cnblogs.com/cswuyg/archive/2010/08/20/1804113.html [布局最清晰] http://blog.csdn.net/wangqiulin123456/article/details/8074891 |
原文地址:https://www.cnblogs.com/meihao1203/p/9368296.html