面试题答案
一键面试- 内存布局分析
- 虚函数表指针:由于
Base
类中有虚函数func
,Derived
类继承自Base
,所以Derived
类的对象中会首先包含一个虚函数表指针(vptr)。这个指针指向一个虚函数表(vtable),虚函数表中存储了虚函数的地址。在Base
类中,虚函数表中存储了Base::func
的地址,Derived
类如果没有重写func
,则虚函数表中对应项仍然是Base::func
的地址;如果Derived
类重写了func
,则虚函数表中该项是Derived::func
的地址。 - 基类成员:接下来是基类
Base
的成员。Base
类中有一个int
类型的成员变量a
,其大小为4字节(假设在32位或64位系统下int
为4字节)。 - 派生类成员:然后是派生类
Derived
自己的成员。Derived
类有一个char
类型的成员变量b
,大小为1字节,以及一个double
类型的成员变量c
,大小为8字节。
- 虚函数表指针:由于
- 内存布局规则
- 继承规则:派生类对象的内存布局首先包含基类子对象的内存布局,然后是派生类自己新增的成员。这确保了派生类对象可以像基类对象一样使用,满足多态性和继承的语义。
- 虚函数规则:含有虚函数的类(或从含有虚函数的类派生而来的类)的对象,其内存布局的开头会放置一个虚函数表指针,用于在运行时动态绑定虚函数。
- 确定大小
- 对齐规则:在计算对象大小时,需要考虑内存对齐。假设默认对齐方式(通常为最大成员变量的大小对齐,这里
double
大小为8字节,所以按8字节对齐)。 - 计算过程:虚函数表指针大小通常为4字节(32位系统)或8字节(64位系统),这里假设64位系统,vptr为8字节。
a
为4字节,补齐到8字节(因为要按8字节对齐),b
为1字节,补齐到8字节,c
为8字节。 - 最终大小:所以
Derived
类对象的大小为8 + 8 + 8 + 8 = 32
字节。
- 对齐规则:在计算对象大小时,需要考虑内存对齐。假设默认对齐方式(通常为最大成员变量的大小对齐,这里
综上所述,Derived
类实例化对象的内存布局为虚函数表指针在前,接着是基类Base
的成员a
(可能有补齐),然后是派生类Derived
的成员b
(可能有补齐)和c
,其大小为32字节(在上述假设的64位系统和对齐方式下)。