面试题答案
一键面试虚函数表与 RTTI 的内在联系
- 虚函数表:在 C++ 中,当一个类包含虚函数时,编译器会为该类生成一个虚函数表(vtable)。每个包含虚函数的对象都有一个指向其所属类虚函数表的指针(vptr)。虚函数表是一个函数指针数组,存储了类中虚函数的地址。当通过基类指针或引用调用虚函数时,程序会根据 vptr 找到对应的虚函数表,进而调用正确的函数。
- RTTI:运行时类型识别(RTTI)允许程序在运行时确定对象的实际类型。RTTI 主要通过 typeid 运算符和 dynamic_cast 运算符来实现。RTTI 依赖于虚函数机制,因为虚函数表为实现 RTTI 提供了关键信息。
RTTI 借助虚函数表的实现
- typeid 运算符:
- 原理:当对一个多态类型的对象或指针使用 typeid 运算符时,如果该对象是通过指针访问且指针类型为多态类型(即包含虚函数的类的指针),编译器会借助虚函数表来确定对象的实际类型。虚函数表的第一个条目通常存放了指向该类类型信息(type_info 对象)的指针。当使用 typeid 时,程序会沿着对象的 vptr 找到虚函数表,然后从虚函数表的第一个位置获取指向 type_info 对象的指针,通过这个 type_info 对象可以获取对象的实际类型信息,如类名等。
- 底层数据结构:涉及虚函数表(vtable)和 type_info 结构体。type_info 结构体存储了类型的相关信息,如类型名称等。
- dynamic_cast 运算符:
- 原理:当使用 dynamic_cast 进行从基类指针或引用到派生类指针或引用的转换时,如果是多态类型,它会借助虚函数表来进行类型检查。它首先通过对象的 vptr 找到虚函数表,然后从虚函数表获取类型信息,与目标类型进行比较。如果类型匹配,则转换成功,返回指向派生类对象的指针或引用;如果不匹配,则返回空指针(对于指针转换)或抛出 std::bad_cast 异常(对于引用转换)。
- 底层操作:在运行时遍历虚函数表获取类型信息并进行类型比较。如果是指针转换,在类型匹配时,计算目标对象在内存中的偏移量,以正确调整指针。
总结
虚函数表为 RTTI 的实现提供了关键的运行时信息。typeid 和 dynamic_cast 运算符借助虚函数表中的类型信息指针来确定对象的实际类型,实现运行时类型识别和安全的类型转换。 虚函数表、vptr 以及 type_info 结构体等底层数据结构共同协作,完成 RTTI 的各项功能。