面试题答案
一键面试虚函数表在C++多继承环境下的构建
- 单一虚函数表:在单继承中,每个有虚函数的类只有一个虚函数表(vtable),表中存放着类的虚函数地址。
- 多继承下的虚函数表:在多继承时,类会有多个虚函数表,每个虚函数表对应一个直接基类。假设有类
Derived
继承自Base1
、Base2
、Base3
,且这些类都有虚函数。那么Derived
对象的内存布局中会有与Base1
、Base2
、Base3
相对应的虚函数表。Derived
类重写的虚函数,会在对应的基类虚函数表中更新其地址;如果Derived
没有重写某个基类的虚函数,虚函数表中就保存基类虚函数的地址。
对象指针偏移在多继承场景中的情况
- 指针偏移现象:由于多继承下对象内存布局包含多个基类子对象,不同基类子对象在内存中的起始位置不同。当使用指向派生类对象的指针进行类型转换时,指针需要进行偏移以正确指向不同基类子对象。例如,假设有
Derived
继承自Base1
和Base2
,Base1
和Base2
有不同的大小和内存布局。Derived
对象中Base1
子对象和Base2
子对象位置不同,若有Derived* d = new Derived(); Base1* b1 = d; Base2* b2 = d;
,b1
和b2
实际指向Derived
对象内不同位置,编译器会自动调整指针偏移。 - 理解与处理:理解这种偏移是基于对象内存布局的原理,编译器为了保证正确的多态行为和对象访问进行指针调整。在实际编程中,尽量使用
dynamic_cast
进行类型转换,它会在运行时检查类型安全性并正确处理指针偏移。避免使用static_cast
进行不安全的指针转换,以免导致未定义行为。若要手动处理指针偏移,需要非常清楚对象的内存布局,这通常很复杂且容易出错,所以依赖编译器的自动处理和dynamic_cast
更为可靠。