对象大小的判断

在判断一个C++对象大小时,并不能直接根据字面意义上的数据进行简单的叠加,因为除了这些数据,编译器还额外做了很多工作,我们需要注意如下几点。


1. 对于空对象的判断,有如下代码:

class A   
{   
};  
int main(void)
{
    A* p = new A;
    cout<<"A="<<sizeof(*p)<<endl;    
}

输出结果是:

A=1

很奇怪,为什么一个空对象大小为1.
对象的创建过程:1.分配空间 2. 调用构造函数对空间初始化 3.返回对象指针
如果对象大小为0,那么连空间都无法申请。对于定义为空的类,为了能够创建对象,编译器会安插一个char数据,用以表示不同的A对象。
可以测试,空类的直接继承子类,大小也为1,对空类的多重继承,大小也为1

2. 虚函数指针占用大小

2.1 若类中没有虚函数,编译器不会为其生成虚表指针。
class A   
{   
    int a;
};  

class F : A
{
    int f;
};

A=4 F=8

可见其中并没有虚表指针。

2.2 当类中有虚函数或者父类中有虚函数时,系统会生成虚表指针指向虚表,虚表不占用对象空间,但是虚表指针会。
class B   
{   
    int b;
    virtual void func0() {}; 
};

sizeof(B) =  sizeof(vptr) + sizeof(int) = 8;

单一继承,只会有一个虚表指针,但是如果有多重继承,会有多个虚表指针,比如:
class B   
{
    int b;
    virtual void func0(){} 
}; 
class C  
{
    char ch1;
    char ch2;
    virtual void func()   { }  
    virtual void func1()  { } 
};


class E: public B, public C
{   
    int e;   
    virtual void func0()  { } 
    virtual void func1()  { }
};


E的结构:
 

多重继承下 大小SIZEOF(B) + sizeof(C) + e = 8 + 8 + 4 = 20
在此处编写了相关测试程序
int _tmain(int argc, _TCHAR* argv[])
{
	E* e = new E();

	printf("%x\n", e);
	printf("%x\n", &e->b);
	printf("%x\n", &e->ch1);
	typedef void (*Fun)();

	Fun p = (Fun)*(int*)*(int*)e;
	p();

	printf("%x\n", &e->ch1 - 4);
	printf("%x\n", &e->ch1);
	p = (Fun)*(int*)*(int*)(&e->ch1 - 4);
	p();

	getchar();
	return 1;
}

测试结果:


Fun p = (Fun)*(int*)*(int*)e;
p();

printf("%x\n", &e->ch1 - 4);
p();

可以发现,第二个虚表指针介于b(1a44ac)与ch1(1a44b4),发现正好有四个字节的空闲空间,这个空间就是用于存放第二个虚表指针。

多重继承有如下需要注意的问题:
class A   
{   
public:
	int a;
	virtual void func0(){cout<<"A: func0"<<endl;};
};  


class B   
{
public:
	int b;
	virtual void func0() {cout<<"B: func0"<<endl;};
}; 

class C  : public A, public B
{
public:
	char ch1;
	char ch2;
};

int main()
{
    C* c = new C;
    c->func0();
}

编译报错:
error C2385: 对“func0”的访问不明确
1>        可能是“func0”(位于基“A”中)
1>        也可能是“func0”(位于基“B”中)

因为无法确定调用基类A中的函数还是调用B中的函数。若在C中实现函数func0(),则OK。
子类中增加虚函数,有两个虚函数表,函数指针放在主基类的虚表中
虚表更新:上例中A,B中都有方法func0(),如果C中也实现了方法func0(),那么A,B中的虚表都会将虚表中的方法更新为
C::func0();







转载于:https://my.oschina.net/myspaceNUAA/blog/76491

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值