虚指针的对齐_第二门课_第一周_作业

喜欢的朋友可以关注收藏一下:  http://blog.csdn.NET/qq_31201973

本文如有错误,请及时私信我。

原版要求:

分别给出下面的类型Fruit和Apple的类型大小(即对象size),并通过画出二者对象模型图以及你的测试来解释该size的构成原因。

 

class Fruit{test
   int no;
   double weight;
   char key;
public:
   void print() {   }
   virtual void process(){   }
};
   
class Apple: public Fruit{
   int size;
   char type;
public:
   void save() {   }
   virtual void process(){   }
};

 

Fruit的类型大小(即对象size):32

Apple的类型大小(即对象size):40

(win10,vs2013编译有效)

对象模型图(字节对齐,虚基类表指针字节对齐):

 

上图是我根据测试得出的对齐模型表

 

在c++对象模型中会有对齐规则:

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16 来改变这一系数,其中的n就是你要指定的“对齐系数”。
规则:
1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐 按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的 数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
3、当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

除了这三条规则之外虚指针会单独对齐:

    类Fruit有虚函数,所以会有一个隐藏的成员,虚函数表指针,放在类对象的最开始的地方,因为类Fruit的最大对齐参数就是隐藏成员本身的对齐参数8了,所以在后面补充4个字节。然后就是成员变量no,后面是weight对齐参数是8,所以在no后面补充四个字节,然后是key,对齐系数是1,所以紧跟在后面。因为Fruit本身也要自身对齐,按照它的成员中最大的那个有效对齐作为自己的自身对齐,也就是weight,所以Fruit本身要按照8字节对齐,所以在key后面要填充7个字节才满足对齐规则。

sizeof(Fruit)=4+4+4+4+8+1+7=32            √

      类Apple有虚函数,所以会有一个隐藏的成员,虚函数表指针,放在类对象的最开始的地方,因为类Apple的最大对齐参数就是隐藏成员本身的对齐参数8了,所以在vptr后面补充4个字节。然后就是成员变量no,后面是weight对齐参数是8,所以在no后面补充四个字节,然后是key,对齐系数是1,所以紧跟在后面,然后是size,对齐系数是4所以补充3个字节,然后是type对齐系数是1紧跟在后面。因为Apple本身也要自身对齐,按照它的成员中最大的那个有效对齐作为自己的自身对齐,也就是weight,所以Fruit本身要按照8字节对齐,所以在key后面要填充7个字节才满足对齐规则。

sizeof(Apple)=4+4+4+4+8+1+3+4+1+7=40        √

测试代码:

 

 

 

#include<iostream>
using namespace std;

class Fruit{
protected:
	int no;
	double weight;
	char key;
public:
	void print() {
		cout << "sizeof(f1.no)=" << sizeof(this->no) << endl;
		cout << "sizeof(f1.weight)=" << sizeof(this->weight) << endl;
		cout << "sizeof(f1.key)=" << sizeof(this->key) << endl;
	}
	const int* get_no() const { return &no; }
	const double* get_weight() const { return &weight; }
	const char* get_key() const { return &key; }
	virtual void process(){   }  
};

class Apple : public Fruit{
protected:
	int size;
	char type;
public:
	void print() {
		cout << "sizeof(a1.no)=" << sizeof(this->no) << endl;
		cout << "sizeof(a1.weight)=" << sizeof(this->weight) << endl;
		cout << "sizeof(a1.key)=" << sizeof(this->key) << endl;
		cout << "sizeof(a1.no)=" << sizeof(this->size) << endl;
		cout << "sizeof(a1.weight)=" << sizeof(this->type) << endl;
	}
	void save() {   }
	const int* get_size() const { return &size; }
	const char* get_type() const { return &type; }
	virtual void process(){   }
};

int main()
{
	Fruit f1;
	Apple a1;
	int* pf1 = (int*)&f1;
	int* pa1 = (int*)&a1;
	cout <<"Fruit类vptr的大小:"<< sizeof(pf1) << endl;
	f1.print();
	cout << "Fruit类大小:sizeof(f1)=" << sizeof(f1) << endl;
	cout << "Fruit类vptr的地址:" << pf1 << endl;
	cout << "Fruit类no的地址:" << f1.get_no() << endl;
	cout << "Fruit类weight的地址:" << f1.get_weight() << endl;
	cout << "Fruit类key的地址:" << (int*)(f1.get_key()) << endl;
	cout << "Fruit类vtbl的地址:" << (int*)(*pf1) << endl;
	cout << "Fruit::process()的地址:" << (int*)*((int*)(*pf1)) << endl;
	cout << "——————————————————————————" << endl;

	cout << "Apple类vptr的大小:" << sizeof(pa1) << endl;
	a1.print();
	cout << "Apple类大小:sizeof(a1)=" << sizeof(a1) << endl;
	cout << "Apple类vptr的地址:" << pa1 << endl;
	cout << "Apple类no的地址:" << a1.get_no() << endl;
	cout << "Apple类weight的地址:" << a1.get_weight() << endl;
	cout << "Apple类key的地址:" << (int*)(a1.get_key()) << endl;
	cout << "Apple类size的地址:" << a1.get_size() << endl;
	cout << "Apple类type的地址:" << (int*)(a1.get_type()) << endl;
	cout << "Apple类vtbl的地址:" << (int*)(*pa1) << endl;
	cout << "Apple::process()的地址:" << (int*)*((int*)(*pa1)) << endl;



	getchar();
	return 0;
}


测试结果:

 

 

 

参考资料:

1. http://blog.csdn.net/haoel/article/details/1948051/

2. http://blog.csdn.net/chengonghao/article/details/51679743

3.http://blog.csdn.net/hairetz/article/details/4084088

4. http://www.jb51.net/article/36903.htm

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值