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、 在派生类中不对基类的虚函数进行覆盖,同时派生类中还拥有自己的虚函数,如图 2,Base派生出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