#题目说明:
分别给出下面的类型Fruit和Apple的类型大小(即对象size),并通过画出二者对象模型的方式来解释该size的构成原因。
class Fruit { 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() { } };
#资料整理:
*注意点.编译器最终分配内存大小需要考虑"位对齐",规则如下:
1.首先按照声明次序依次保存类中数据对象。
2.若类中存在虚函数在对象起始处会存在虚指针。
3.变量的起始偏移位置设定为自身字节大小的整数倍,以便读取变量时使得cache速度更快。
4.内存分配结束后,需要将当前内存空间补充为最大的基本类型变量的倍数。
*补充:在vs编译环境中,数据成员的起始地址必须为内部最大数据类型的整数倍。则存在虚指针时需要考虑补位对齐。
#作业发布:
根据叶卡林娜的考虑方法,进行试验验证。
思路整理:首先验证虚指针所存放在内存中的位置,及其占有内存单元。其次验证各个数据对象所在内存及其补位对齐方式。
需要注意,继承关系中虚指针是否单元新开辟的内存。
测试代码如下:
#include <iostream> using namespace std; class Fruit { public: int no; double weight; int key; public: void print() { } virtual void process() {} }; class Apple : public Fruit { public: int size; int type; public: void save() { } virtual void process() { } }; int main() { cout << "sizeof(Fruit) = " << sizeof(Fruit) << endl; cout << "sizeof(Apple) = " << sizeof(Apple) << endl; Fruit fruit; Apple apple; cout << "Fruit = " << &fruit << endl; cout << "Fruit.no = " << &fruit.no << endl; cout << "Fruit.weight = " << &fruit.weight << endl; cout << "Fruit.key = " << &fruit.key << endl; cout << "Apple = " << &apple << endl; cout << "Apple.no = " << &apple.no << endl; cout << "Apple.weight = " << &apple.weight << endl; cout << "Apple.key = " << &apple.key << endl; cout << "Apple.size = " << &apple.size << endl; cout << "Apple.type = " << &apple.type << endl; system("pause"); return 0; }
win10 vs2017 运行结果如下:
sizeof(Fruit) = 32 sizeof(Apple) = 40 Fruit = 003DF8D4 Fruit.no = 003DF8DC Fruit.weight = 003DF8E4 Fruit.key = 003DF8EC Apple = 003DF8A4 Apple.no = 003DF8AC Apple.weight = 003DF8B4 Apple.key = 003DF8BC Apple.size = 003DF8C4 Apple.type = 003DF8C8
*补充:类中若存在虚函数(包括继承)则一定存在且仅存在一个虚函数指针指向虚表,虚表中存放虚函数地址。
#对象模型:
根据上述摘要及测试代码整理,对象模型如下:
#补充,无论堆中或者栈中构建的对象其内存大小均相同。