C++各种类继承关系的内存布局
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;}
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::$vftable@:
1> | &A_meta
1> | 0
1> 0 | &A::f
|
1> B::$vftable@:
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::$vftable@:
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::$vftable@:
1> | &A_meta
1> | 0
1> 0 | &A::f
|
1> B::$vftable@B@:
1> | &B_meta
1> | 0
1> 0 | &B::fb2
1>
1> B::$vbtable@:
1> 0 | -4
1> 1 | 12 (Bd(B+4)A)
1>
1> B::$vftable@A@:
1> | -16
1> 0 | &(vtordisp) B::f
1>
1> B::f this adjustor: 16
1> B::f2 this adjustor: 0
|
1> B::$vbtable@:
1> 0 | 0
1> 1 | 8 (Bd(B+0)A)
1>
1> B::$vftable@:
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::$vbtable@:
1> 0 | 0
1> 1 | 12 (Bd(B+0)A)
1>
1> B::$vftable@:
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})
|
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::$vftable@:
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::$vftable@:
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::$vftable@:
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::$vftable@Base1@:
1> | &Derived_meta
1> | 0
1> 0 | &Derived::f
1> 1 | &Base1::g
1> 2 | &Base1::h
1> 3 | &Derived::g1
1>
1> Derived::$vftable@Base2@:
1> | -8
1> 0 | &thunk: this-=8; goto Derived::f
1> 1 | &Base2::g
1> 2 | &Base2::h
1>
1> Derived::$vftable@Base3@:
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::$vftable@Derived@:
1> | &Derived_meta
1> | 0
1> 0 | &Derived::g1
1>
1> Derived::$vbtable@:
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::$vftable@Base1@:
1> | -16
1> 0 | &(vtordisp) Derived::f
1> 1 | &Base1::g
1> 2 | &Base1::h
1>
1> Derived::$vftable@Base2@:
1> | -28
1> 0 | &(vtordisp) thunk: this-=12; goto Derived::f
1> 1 | &Base2::g
1> 2 | &Base2::h
1>
1> Derived::$vftable@Base3@:
1> | -40
1> 0 | &(vtordisp) thunk: this-=24; goto Derived::f
1> 1 | &Base3::g
1> 2 | &Base3::h
|
1> Derived::$vbtable@:
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::$vftable@Base1@:
1> | -12
1> 0 | &(vtordisp) Derived::f
1> 1 | &Base1::g
1> 2 | &Base1::h
1>
1> Derived::$vftable@Base2@:
1> | -24
1> 0 | &(vtordisp) thunk: this-=12; goto Derived::f
1> 1 | &Base2::g
1> 2 | &Base2::h
1>
1> Derived::$vftable@Base3@:
1> | -36
1> 0 | &(vtordisp) thunk: this-=24; 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::$vftable@:
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::$vftable@:
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::$vftable@:
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::$vftable@B1@:
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::$vftable@B2@:
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
|
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
|
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::$vftable@:
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::$vftable@B1@:
1> | &B1_meta
1> | 0
1> 0 | &B1::f1
1> 1 | &B1::Bf1
1>
1> B1::$vbtable@:
1> 0 | -4
1> 1 | 16 (B1d(B1+4)B)
1>
1> B1::$vftable@B@:
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::$vftable@B2@:
1> | &B2_meta
1> | 0
1> 0 | &B2::f2
1> 1 | &B2::Bf2
1>
1> B2::$vbtable@:
1> 0 | -4
1> 1 | 16 (B2d(B2+4)B)
1>
1> B2::$vftable@B@:
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::$vftable@B1@:
1> | &D_meta
1> | 0
1> 0 | &D::f1
1> 1 | &B1::Bf1
1> 2 | &D::Df
1>
1> D::$vftable@B2@:
1> | -16
1> 0 | &D::f2
1> 1 | &B2::Bf2
1>
1> D::$vbtable@B1@:
1> 0 | -4
1> 1 | 40 (Dd(B1+4)B)
1>
1> D::$vbtable@B2@:
1> 0 | -4
1> 1 | 24 (Dd(B2+4)B)
1>
1> D::$vftable@B@:
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
|
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
|
[原理最清晰]
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
|
C++各种类继承关系的内存布局的更多相关文章
- 浅析GCC下C++多重继承 & 虚拟继承的对象内存布局
继承是C++作为OOD程序设计语言的三大特征(封装,继承,多态)之一,单一非多态继承是比较好理解的,本文主要讲解GCC环境下的多重继承和虚拟继承的对象内存布局. 一.多重继承 先看几个类的定义: 01 ...
- c++继承中的内存布局
今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化 译 译者前言 一个C ...
- 从汇编看c++的虚拟继承以及其内存布局(一)
先看第一种最简单的情形,所有类中没有任何虚函数的菱形继承. 下面是c++源码: class Top {//虚基类 public: int i; Top(int ii) { i = ii; } }; c ...
- C++对象模型:单继承,多继承,虚继承,菱形虚继承,及其内存布局图
C++目前使用的对象模型: 此模型下,nonstatic数据成员被置于每一个类的对象中,而static数据成员则被置于类对象之外,static和nonstatic函数也都放在类对象之外(通过函数指针指 ...
- 继承关系在内存和DB中的映射
使用 将若干相似的类映射为单表,对拥有许多特殊数据的类使用具体表继承. 对高层次使用类表继承,对低层次使用具体表继承. Single Table Inheritance 在DB中将类继承层次设计为一个 ...
- C++中继承 声明基类析构函数为虚函数作用,单继承和多继承关系的内存分布
1,基类析构函数不为虚函数 #include "pch.h" #include <iostream> class CBase { public: CBase() { m ...
- 转: c++继承中的内存布局
英文原文: http://www.openrce.org/articles/files/jangrayhood.pdf 翻译: http://blog.csdn.net/jiangyi711/arti ...
- 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。
本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...
- 虚继承之单继承的内存布局(VC在编译时会把vfptr放到类的头部,这和Delphi完全一致)
C++2.0以后全面支持虚函数与虚继承,这两个特性的引入为C++增强了不少功能,也引入了不少烦恼.虚函数与虚继承有哪些特性,今天就不记录了,如果能搞了解一下编译器是如何实现虚函数和虚继承,它们在类的内 ...
随机推荐
- NGUI中处理层级问题的几个方法总结
1.获得ui界面的UIPanel的最大层级: static int GetUIMaxDepth(Transform root) { UIPanel[] panels = root.GetCompone ...
- English trip V1 - 9.Do you Ever Say Never? 你有没有说永远不会? Teacher:Lamb Key: Adverbs of frequency (频率副词)
In this lesson you will learn to describe what you do at home. 在本课中,您将学习如何描述您在家中所做的事情. 课上内容(Lesson) ...
- OnSen UI结合AngularJs打造”美团"APP"我的”页面 --Hybrid App
1.页面效果图: 演示地址:http://www.nxl123.cn/bokeyuan/meiTuanDemo_mine/ 2.核心代码 mine.html: <ons-page id=&quo ...
- patch-test-and-proc
实验环境 Ubuntu 14.04.5 LTS Linux - 4.15.6 为单个文件进程补丁操作 在桌面 Desktop 建立文件夹 patch ,作为实验用,然后进入patch 文件夹.建立测试 ...
- 树上第k大联通块
题意:求树上第k大联通块 n,k<=1e5 考虑转化为k短路的形式. 也就是要建出一张图是的这条图上每一条S到T的路径都能代表一个联通块. 点分治建图 递归下去,假定每个子树的所有联通块中都可以 ...
- 51nod1647 小Z的trie
题意:给你n个字符串,m次查询,每次问你第p个字符串的s到t的字符串在n个字符串建成的字典树上出现了多少次 题解:先建出字典树,在字典树上拓展sam,记录每个子串的出现次数.查询时只需找出在字典树上的 ...
- python爬虫---requests库的用法
requests是python实现的简单易用的HTTP库,使用起来比urllib简洁很多 因为是第三方库,所以使用前需要cmd安装 pip install requests 安装完成后import一下 ...
- 【转】JavaScript数组方法大全
数组在笔试题中出现的概率最高的类型之一,JavaScript中的数组与其他语言中的数组有些区别,为了方便以后查看数组的方法,现将对数组的操作方法进行汇总整理. 数组创建 JavaScript中创建数组 ...
- 小程序-wepy学习
组件通信与交互 推荐网址:https://tencent.github.io/wepy/document.html#/?id=%e7%bb%84%e4%bb%b6%e9%80%9a%e4%bf%a1% ...
- maven plugins
<build> <finalName>lessons</finalName> <plugins> <plugin> <groupId& ...