C/C++类的大小计算

1、关于类/对象大小的计算

i、 首先,类大小的计算遵循结构体的对齐原则

ii、 类的大小与普通数据成员有关,与成员函数和静态成员无关。即普通成员函数,静态成员函数,静态数据成员,静态常量数据成员均对类的大小无影响

iii、  虚函数对类的大小有影响,是因为虚函数表指针VPTR带来的影响

iv、  虚继承对类的大小有影响,是因为虚基表指针带来的影响

空类的大小是一个特殊情况,空类的大小为1

2、需要注意的是类的大小计算涉及内置类型的大小,及字节对齐原则,所以要明确计算机位长。在32位机器上,int的大小为4Bytes,指针则为机器字长4Bytes。

3、空类的大小

c++规定:凡是一个独立的(非附属)对象都必须具有非零大小——即空类大小不为0.

i、 空类的继承(不计算空类字节1

ii、 一个类包含一个空类对象数据成员(需要计算空类字节1

4、含有虚函数成员

         特别需要考虑 秘密指针VPTR(会占用类的大小) ,指向对象的虚函数表(VTABLE),见图 1,VTABLE被该类所有对象共有,在定义该类时被初始化。而VPTR则是每个类对象都有独立的一份,且在该对象被构造时被初始化。


图1 VPTR指向虚函数表

5、针对基类含有虚函数的继承进行讨论

a、  在派生类中不对基类的虚函数进行覆盖,同时派生类中还拥有自己的虚函数,如图 2Base派生出Derive


图2 不覆盖情况下的虚函数表

         i、虚函数按照其声明顺序放于表中

         ii、基类的虚函数在派生类的虚函数前面

派生类大小是基类和派生类的数据成员的大小+指针的大小。

b、在派生类中对基类的虚函数进行覆盖,如图3


图3 存在覆盖情况下的虚函数表

         i、覆盖的f()函数被放到了虚表中原来基类虚函数的位置

         ii、没有被覆盖的函数

派生类的大小仍是基类和派生类的非静态数据成员的大小+一个vptr指针大小。

c、多继承:无虚函数覆盖,如图4


图4 多继承不存在覆盖情况下的虚函数表

         i、每个基类都有自己的虚表

         ii、派生类的成员函数被放到了第一个基类的表中。(所谓的第一个基类是按照声明顺序来判断的)

派生类的大小是基类和派生类的非静态数据成员的大小+三个vptr指针大小。

d、多重继承,含虚函数覆盖,如图5



图5 多继承存在覆盖情况下的虚函数表

       i、需要与不存在覆盖情况下的虚函数表对比,此外三个基类虚函数表中的f()的位置被替换成了派生类的函数指针,于是,就可以通过任一静态类型的基类类来指向派生类,并调用派生类的f(),难道这就是实现了动态绑定(多态)嘛,是的,这是!!!!

派生类的大小是基类和派生类的非静态数据成员的大小+三个vptr指针大小。

6、虚继承的情况(由于对虚继承层次的对象的内存布局,在不同编译器实现有所区别)

         gcc编译下,不管是否虚继承,都是将虚表指针在整个继承关系中共享,不共享的是指向虚基类的指针。(此块感觉出处作者讲解的不是很清楚,没太理解!)

参考出处:https://blog.csdn.net/fengxinlinux/article/details/72836199

猜你喜欢

转载自blog.csdn.net/tt_love9527/article/details/80813909
今日推荐