面试题答案
一键面试- 对象的内存布局
- 基类A:
- 当类A中有虚函数时,其对象在内存中首先包含一个虚函数表指针(vptr),用于指向虚函数表。虚函数表是一个存储类中虚函数地址的数组。之后是类A本身定义的成员变量(如果有的话)。
- 派生类B:
- 派生类B的对象内存布局,首先是基类A的部分,即虚函数表指针(vptr)和基类A的成员变量(按照基类A中的布局顺序)。这部分是因为B继承自A,所以要包含A的所有非静态成员。
- 接着是派生类B自己定义的成员变量,按照在B类中声明的顺序排列。
- 基类A:
- 编译器对虚函数表指针和成员变量内存分布的管理
- 虚函数表指针:
- 编译器在生成类的对象布局时,会为每个包含虚函数的类(包括基类A和派生类B)创建一个虚函数表。
- 当创建对象时,编译器会在对象内存布局的起始位置放置虚函数表指针,使其指向对应的虚函数表。对于派生类B,编译器会根据B对虚函数的覆盖情况来填充虚函数表。如果B覆盖了基类A的虚函数,那么虚函数表中对应的虚函数地址就是B中覆盖后的函数地址;如果B没有覆盖某个虚函数,虚函数表中该函数地址仍然是基类A中虚函数的地址。
- 成员变量内存分布:
- 对于基类A的成员变量,编译器按照它们在A类中声明的顺序,在虚函数表指针之后分配内存空间。
- 对于派生类B自己的成员变量,编译器在基类A部分(虚函数表指针和基类成员变量)之后,按照B类中声明的顺序分配内存空间。编译器通过这种固定的布局方式,使得程序在运行时能够准确地访问对象的成员变量和虚函数。
- 虚函数表指针: