简单的含虚函数的基类和子类
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(){ }
};
由于 定义了虚函数,对于基类和子类,在内存的开头都会有一个指向虚函数表的指针,在32位编译器下,占4字节。
派生类继承了基类的全部内存,可以想象成派生类有两部分,一部分是完整的基类数据,另一部分是派生类自己定义的。
加入两个不含虚函数的对照来看
//没有虚函数的继承
class Fruit_not_virtual
{
int no;
double weight;
char key;
public:
void print() { }
void process(){ }
};
class Apple_not_virtual : public Fruit_not_virtual
{
int size;
char type;
public:
void save() { }
void process(){ }
};
测试
int main()
{
cout << "The size of Fruit: " << sizeof(Fruit) << endl;
cout << "The size of Apple: " << sizeof(Apple) << endl;
cout << "The size of Fruit_not_virtual: " << sizeof(Fruit_not_virtual) << endl;
cout << "The size of Apple_not_virtual: " << sizeof(Apple_not_virtual) << endl;
return 0;
}
运行结果
Vs2013运行结果 :
The size of Fruit: 32
The size of Apple: 40
The size of Fruit_not_virtual: 24
The size of Apple_not_virtual: 32
G++运行结果是 :
The size of Fruit: 20
The size of Apple: 28
The size of Fruit_not_virtual: 16
The size of Apple_not_virtual: 24
输出的原因与数据对齐有很大的关系。
数据对齐就是一种C++中的类型在内存中空间分配策略。每一种类型存储的起始地址,都要求是一个对齐模数的整数倍。目的在于方便CPU处理内存中的数据,提高处理效率。
有一些对齐模数的概念
- 自定义类型的自身对齐模数(struct 、class)
等同于其成员中最大的自身对齐模数
- 指定对齐模数
我们给编译器指定的对齐模数 - 有效对齐模数
有些编译器指定对齐模数与类型自身对齐模数的较小的值,就是实际生效的对齐模数。实际上不同编译器会有差别的。
在Fruit类中自身对齐模数是8字节(double),指定对齐模数一般情况下是处理器位数,32位处理器也就是4字节,以4字节为有效对齐模数。也就是G++的运行结果。VS2013的结果有所不同,查阅网上资料,VS2013的指定的对齐模数是8字节,类型自身对齐模数是8字节时,选择8字节为有效对齐模数,符合上面的运行结果。所以G++和VS2013不同的运算结果是由于编译器指定对齐模式不同引起的。
再来实验一下数据对齐,把所有double类型改为int类型
class Fruit
{
int no;
int weight;
char key;
public:
void print() { }
virtual void process(){ }
};
class Apple: public Fruit
{
int size;
int type;
public:
void save() { }
virtual void process(){ }
};
运行结果
Vs2013运行结果 :
The size of Fruit: 16
The size of Apple: 24
The size of Fruit_not_virtual: 12
The size of novirtual_Apple: 20
G++运行结果是 :
The size of Fruit: 16
The size of Apple: 24
The size of Fruit_not_virtual: 12
The size of novirtual_Apple: 20
结果是一致的,应为此时两种编译器的有效对齐模数都是4字节。