- 虚函数表的存储位置
- 在C++中,当类包含虚函数时,编译器会为每个包含虚函数的类生成一个虚函数表(vtable)。对于定义在动态链接库(DLL)中的包含虚函数的类,虚函数表存储在DLL的代码段(text segment)中。这是因为虚函数表本质上是一个函数指针数组,它是类的元数据的一部分,在编译时就确定了,并且在运行时不会改变,所以适合存储在代码段这种只读区域。当主程序加载DLL时,DLL的代码段被映射到主程序的地址空间中,这样主程序就可以通过对象的虚函数指针(vptr)访问到虚函数表。
- 虚函数表与RTTI机制的协同工作
- 编译器实现:
- 编译器在生成代码时,对于使用了RTTI(如
typeid
操作符)的类,除了生成虚函数表,还会生成类型信息数据结构(type_info)。这个类型信息数据结构包含了类的名称等信息,用于在运行时识别对象的类型。
- 虚函数表和类型信息数据结构紧密相关。编译器会在虚函数表中添加一个指向类型信息数据结构的指针。通常,这个指针位于虚函数表的第一个位置(但这不是标准规定的,不同编译器实现可能略有差异)。
- 运行时行为:
- 当使用
typeid
操作符时,首先会通过对象的虚函数指针(vptr)找到虚函数表。由于虚函数表中包含了指向类型信息数据结构的指针,通过这个指针就可以获取到具体的类型信息(type_info)。例如,对于以下代码:
class Base {
public:
virtual void func() {}
};
class Derived : public Base {
public:
void func() override {}
};
Base* ptr = new Derived();
typeid(*ptr);
- 在运行时,`typeid(*ptr)`首先通过`ptr`所指向对象的虚函数指针找到虚函数表,然后从虚函数表中获取指向`Derived`类类型信息数据结构的指针,从而确定对象实际的类型是`Derived`。这样,RTTI机制就利用虚函数表实现了运行时对象类型的识别。