C++中类所占内存,父类与子类所占内存大小的关系(详细记忆)

10 篇文章 0 订阅

写在前面的话(就先听听)

最近面试一直被面试官问道:

  • 一个类有什么什么变量,静态变量等,请问这个类所占内存多少字节呢?
  • 假如这个类含有若干个虚函数,然后还有子类又定义了一些的自定义成员和成员函数,还有虚函数之类的?那么子类占用多少字节呢?
  • 然后子类又继承了一个孙子类,孙子类有添加了若干个成员,然后定义了什么函数虚函数之类的,请问孙子类的内存大小又是多少呢?

然后就一直摸棱两可的回答了一通,自己也没有弄清楚,什么大小啊,还有虚函数表怎么继承啊,怎么修改啊,被怼的很厉害,于是下决心自己好好整理一下,希望对大家也有帮助。

正文

首先,我们在计算这个类所占内存大小的时候,心里应该有6个宗旨,总结就是:(后面会有解释原因)

  1. 空类占用1个字--------------------------------------------------------1(详情见知乎)
  2. 静态成员变量不占内存大小----------------------------------------0
  3. 普通成员函数不占内存大小----------------------------------------0
  4. 只要含有虚函数(继承的或者是自定义)的占内存---------1个字(不是字节,是根据你机器位数变化的)
  5. 所有的非静态成员变量---------------------------------------------本身类定义的成员变量总和+父类继承下来的所有变量总和
  6. 注意字节对齐原则(整字数)

只要把这6个原则记住了,问题不大了。但是呢除了记住这几个大的原则呢,还要知道为什么最好。下面就一一对5个原则进行补充。

 

详细分析(配有参考链接):

  • 为什么空类占用1个字:

答案就是因为https://blog.csdn.net/zhaoxd200808501/article/details/72845691(看看别人大牛写的)

简单来说就是系统为了标识一个类,不占用内存在什么地方记录这个类的存在呢,那么怎么记录呢,C/C++都是通过指针(一个字)来记录,所以就不为空。

  • 2-3这两个记住就行了,静态变量已经不属于某个对象了,还有成员函数,可以将它们看作是“游离”的内存块即可。
  • 第四条应该注意的是:
    • 一个类中不管有多少个虚函数,虚函数表指针永远只有一个(只占一个字),这个指针是虚函数地址数组的首地址。数组元素是各个虚函数的地址,因此只需要知道这个首地址,那么就可以找到所有的虚函数。
    • 子类继承父类的时候:
      • 父类有虚函数,如果子类没有虚函数,那么计算子类内存大小的时候,子类继承了父类虚函数,他就含有了虚函数,他就要加上那个虚函数表的一个字的内存大小;
      • 父类有虚函数,但是自己也定义的虚函数或者覆盖了父类的虚函数,这样子类也算是有了很多虚函数,虚函数表也是同样占用一个字的内存大小。
      • 父类没有虚函数,子类含有虚函数:就在父类基础上加上一个字虚函数表的大小
      • 父类和子类都没有那就什么都不用加了呀。
    • 孙子类和儿子类也是按照父类和子类的方法相同。
  • 第5条需要注意的一种情况是大家会有这样的疑问:假如父类的非静态成员变量是私有private的话,子类根本不继承啊,那么子类计算内存大小的时候还要加上这些父类私有变量吗?

答案是“加上”。即使没有权限不能使用这些变量,但是计算子类的内存大小的时候也要加上父类继承下来的成员变量大小。不够整个字数的凑够整个字数就可以了。

总结起来就是:

子类内存大小=父类内存大小+子类自定义的成员变量大小

详细的各种图案可以查看https://blog.csdn.net/changyang208/article/details/78668462 这位大佬写的很详细很详细。

希望不明白的或者写的有误的,大家可以留言多多指正和讨论。

 

 

 

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
C++,继承关系父类并不直接将自身内存复制给子类子类对象包含父类对象的成员,并且可以访问父类的成员函数和成员变量,但是子类对象并不是父类对象的复制。 当创建一个子类对象时,子类对象分配自己的内存空间,并包含父类对象的成员。子类对象的内存布局,通常先包含父类的成员,然后再添加子类自己的成员。这样,子类对象可以直接访问父类的成员。 下面是一个简单的示例,演示了继承关系子类对象包含父类对象的成员: ```cpp #include <iostream> class Parent { public: int parentData; void parentMethod() { std::cout << "Parent method" << std::endl; } }; class Child : public Parent { public: int childData; void childMethod() { std::cout << "Child method" << std::endl; } }; int main() { Child child; child.parentData = 10; child.childData = 20; std::cout << "Parent data: " << child.parentData << std::endl; std::cout << "Child data: " << child.childData << std::endl; child.parentMethod(); child.childMethod(); return 0; } ``` 在上述代码,`Child`类继承自`Parent`类。创建`Child`类的对象`child`时,它分配自己的内存空间,并包含`Parent`类的成员`parentData`,以及`Child`类自己的成员`childData`。通过对象`child`可以直接访问父类的成员函数`parentMethod()`和子类的成员函数`childMethod()`。 需要注意的是,由于子类对象包含父类对象的成员,因此在使用继承关系时需要注意内存布局和访问权限的相关问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值