派生类占用内存大小
本帖最后由 Jeter_Lin 于 2013-12-15 19:02:23 编辑 #include<iostream>
using namespace std;
class B
{
public:
virtual void bf(){}
virtual ~B(){ cout <<"B::~B()"<<endl; }
};
class D:public B
{
char d;
public:
virtual ~D() { cout <<"D::~D()"<<endl; }
};
int main(void)
{
cout << "sizeB:" << sizeof(B) << " sizeD:"<< sizeof(D) <<endl;
return 0;
}
代码如上,问题如下
D类如果不继承B类,其sizeof结果是8,因为是D类需要保存虚函数表的指针vfptr(4字节),于是其中的变量char d因为字节对齐缘故需要补齐到4字节,问题在于,D类继承B类后,sizeof结果依旧是8,按照网上很多相关文章的说法,此时D类应该是自身的大小加上基类的大小,即8+4=12才对,这是什么原因呢?
P.S.我是在ubuntu 12.04下用其自带的G++编译执行的
[解决办法]
你是不是误会什么了,这个虚函数表并非是指D类的。一个类的虚函数表保管的是它本身以及继承的虚函数的情况,所以应该从最顶层开始维护。如果遇到派生类重名的虚函数就会覆盖虚函数表中的虚函数,如果原本没有就会加入这张表中,一直到该类本身。
如果是单继承就只有1个虚函数表,如果是多继承则会有多个。给你看个例子:
class A
{
public:
virtual void bf(){}
virtual ~A(){}
};
class B:public A
{
public:
virtual void bf(){}
virtual ~B(){ cout <<"B::~B()"<<endl; }
};
class C:public A
{
public:
virtual void bf(){}
virtual ~B(){ cout <<"B::~B()"<<endl; }
};
class D:public B,class C
{
char d;
public:
virtual ~D() { cout <<"D::~D()"<<endl; }
};
class D size(12):
+---
[解决办法]
+--- (base class B)
[解决办法]
[解决办法]
+--- (base class A)
0
[解决办法]
[解决办法]
[解决办法]
{vfptr}
[解决办法]
[解决办法]
+---
[解决办法]
+---
[解决办法]
+--- (base class C)
[解决办法]
[解决办法]
+--- (base class A)
4
[解决办法]
[解决办法]
[解决办法]
{vfptr}
------解决方案--------------------
[解决办法]
+---
[解决办法]
+---
8
[解决办法]
d
[解决办法]
<alignment member> (size=3)
+---
D::$vftable@B@:
[解决办法]
&D_meta
[解决办法]
0
0
[解决办法]
&B::bf
1
[解决办法]
&D::{dtor}
D::$vftable@C@:
[解决办法]
-4
0
[解决办法]
&C::bf
1
[解决办法]
&thunk: this-=4; goto D::{dtor}
D::{dtor} this adjustor: 0
D::__delDtor this adjustor: 0
D::__vecDelDtor this adjustor: 0
看表中的图,虚函数表全部都是从最顶层的class A开始的,然后因为继承了2个class所以有两个vfptr
当然这个还是简单的,把这个例子修改下,用virtual继承,这就是著名的菱形继承问题,你和上面那个对比下:
class A
{
public:
virtual void bf(){}
virtual ~A(){}
};
class B:virtual public A
{
public:
virtual void bf(){}
virtual ~B(){ cout <<"B::~B()"<<endl; }
};
class C:virtual public A
{
public:
virtual void bf(){}
virtual ~B(){ cout <<"B::~B()"<<endl; }
};
class D:public B,class C
{
char d;
public:
virtual ~D() { cout <<"D::~D()"<<endl; }
};
class D size(20):
+---
[解决办法]
+--- (base class B)
0
[解决办法]
[解决办法]
{vbptr}
[解决办法]
+---
[解决办法]
+--- (base class C)
4
[解决办法]
[解决办法]
{vbptr}
[解决办法]
+---
8
[解决办法]
d
[解决办法]
<alignment member> (size=3)
+---
12
[解决办法]
(vtordisp for vbase A)
+--- (virtual base A)
16
[解决办法]
{vfptr}
+---
D::$vbtable@B@:
0
[解决办法]
0
1
[解决办法]
16 (Dd(B+0)A)
D::$vbtable@C@:
0
[解决办法]
0
1
[解决办法]
12 (Dd(C+0)A)
D::$vftable@:
[解决办法]
-16
0
[解决办法]
&(vtordisp) thunk: this-=8; goto B::bf
1
[解决办法]
&(vtordisp) D::{dtor}
D::{dtor} this adjustor: 16
D::__delDtor this adjustor: 16
D::__vecDelDtor this adjustor: 16