接着上一篇继续介绍C++类在内存中的存储方式,上一篇没有涉及到类的继承关系,所以类所占空间 = 非静态成员变量 + 指向虚函数的指针(如果有虚函数)
如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢
3.空类的派生类
// ====== 测试一 ======
class A {
};
class Test : public A{
private:
char c;
};
Test test;
cout << sizeof(test) << endl;
// 运行结果:1
// ====== 测试二 ======
class A {
};
class Test : public A{
private:
A a;
char c;
};
Test test;
cout << sizeof(test) << endl;
// 在MinGW 64bit下编译运行结果:3;在MSVC2017 64bit下编译运行结果:2
解释:
- 若基类是空类,C++标准允许派生类的第一个成员与基类共享地址,故此时的基类不占内存空间
- 若空类的派生类第一个数据成员是被继承的空类,此时的编译器就会给继承过来的基类分配 1Byte(不同的编译器可能不同) 的内存空间,因为C++标准规定类型相同的对象地址必须不同
4.基类有数据成员的派生类
// ====== 测试一 ======
class A {
private:
double d;
char c;
};
class Test : public A{
private:
char c;
};
Test test;
cout << sizeof(test) << endl;
// 在MinGW 64bit下编译运行结果:16;在MSVC2017 64bit下编译运行结果:24
解释:
- 在MinGW 64bit下编译环境下,基类和派生类的数据成员是合在一起计算的内存大小,double(8Byte),char(1Byte),8 + 1 + 1 = 10Byte,补齐最终结果为16Byte
- 在MSVC2017 64bit下编译环境下,基类和派生类的数据成员是先分开计算然后合在一起计算的内存大小,double(8Byte),char(1Byte),基类8 + 1 = 9Byte,补齐为16Byte;派生类16 + 1 = 17Byte,补齐最终结果为24Byte
5.基类有虚函数的派生类
// ====== 测试一 ======
class A {
public:
virtual void func() {
cout << "class A virtual function" << endl;
}
private:
double d;
char c;
};
class Test : public A{
private:
char cc;
};
Test test;
cout << sizeof(test) << endl;
// 在MinGW 64bit下编译运行结果:24;在MSVC2017 64bit下编译运行结果:32
// ====== 测试二 ======
class A {
public:
virtual void func() {
cout << "class A virtual function" << endl;
}
private:
double d;
char c;
};
class Test : public A{
public:
virtual void func1() {
cout << "class Test virtual function" << endl;
}
private:
char cc;
};
Test test;
cout << sizeof(test) << endl;
// 在MinGW 64bit下编译运行结果:24;在MSVC2017 64bit下编译运行结果:32
解释:
- 测试一可看出派生类中继承了基类的虚表指针,内存的计算方式与5相同
- 测试二可看出派生类的虚函数和基类的虚函数共用一张虚函数表,故派生类中只有一个虚表指针
6.虚继承的派生类
// ====== 测试一 ======
class A {
private:
double d;
char c;
};
class Test : virtual public A{
private:
char cc;
};
Test test;
cout << sizeof(test) << endl;
// 运行结果:32
解释:
- 虚继承与虚函数一样同样是多了一个虚表的指针
总结
- 派生类的内存大小 = 基类的内存空间(非静态成员函数 + 虚函数指针(若有虚函数)) + 派生类特有的非静态数据成员的内存空间 + 派生类虚指针(在基类没有虚函数,且派生类有特有的虚函数或虚继承的条件下)
- 以上提到的虚函数,虚继承等后面再写文章具体介绍实现机制,这里就不再过多介绍了
参考文章
[1] C++类的内存分配
[2] C++类的实例化对象的大小之sizeof()
如果未特殊说明,以上测试均是在win10 vs2017 64bit编译器下进行的