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++增强了不少功能,也引入了不少烦恼.虚函数与虚继承有哪些特性,今天就不记录了,如果能搞了解一下编译器是如何实现虚函数和虚继承,它们在类的内 ...
随机推荐
- HTML第五章总结
A Chapter for <img> 前言 这一章讲了 Web 图片 format 的各自的优缺点和elements of 's attributes. Section1:Q1:How ...
- ultragrid
foreach (UltraGridColumn aCol in this.ultraGrid1.DisplayLayout.Bands[0].Columns){this.ultraGrid1.Dis ...
- 基因/转录本/任意特征 表达定量工具之featureCounts使用方法 | 参数详解
featureCounts真的很厉害. 常见的参数(没什么好说的,毕竟是固定的): -a -o input_file1 -F -t -g -Q -T 关键是以下几个参数怎么设置: -f # Perfo ...
- Node版本管理nvm, npm
nvm(node version manger) Node版本管理 nvm是一个简单的bash script来管理多个活动的node.js版本. 安装nvm: 具体看git:https://githu ...
- confirm提示弹出确定和取消按钮
js----> var con = confirm('这是一个确定加取消的提示窗口') if(con==true){ document.write("点击了确定按钮") }e ...
- lanmp中环境变量的更改方法
1.vim /etc/profile 改成: export PATH=$PATH:/www/wdlinux/phps/71/bin/ 然后运行: source /etc/profile
- python 发送邮件+多人+附件 最好用!!!
#!python3#codin=utf-8import yagmail yag = yagmail.SMTP(user='2679813@qq.com', password='mwlgdmwv4rss ...
- Watto and Mechanism CodeForces - 514C (字典树,哈希)
大意: 给定字符串集$S$, 每次询问给出字符串$a$, 求$S$中是否存在一个字符串恰好与$a$相差一个字符. 直接建字典树暴力复杂度是$O(n\sqrt{n})$, 也可以用set维护所有哈希值, ...
- Single Number III leetcode java
问题描述: Given an array of numbers nums, in which exactly two elements appear only once and all the oth ...
- tomcat压缩版配置
下载Jdk并安装 配置Java环境变量 因为需要用services.bat安装,services.bat中 rem Make sure prerequisite environment variabl ...