MST

星途 面试题库

面试题:C++ 虚函数表在动态链接库与运行时类型识别(RTTI)场景下的存储与交互

在一个大型C++项目中,部分类定义在动态链接库(DLL)中,这些类包含虚函数。当主程序加载该DLL并实例化包含虚函数的类对象时,虚函数表存储在哪里?并且在使用运行时类型识别(RTTI)机制,如typeid操作符获取对象类型信息时,虚函数表的存储位置如何与RTTI机制协同工作?请深入探讨其中的原理,包括编译器如何实现以及运行时的具体行为。
41.1万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
  1. 虚函数表的存储位置
    • 在C++中,当类包含虚函数时,编译器会为每个包含虚函数的类生成一个虚函数表(vtable)。对于定义在动态链接库(DLL)中的包含虚函数的类,虚函数表存储在DLL的代码段(text segment)中。这是因为虚函数表本质上是一个函数指针数组,它是类的元数据的一部分,在编译时就确定了,并且在运行时不会改变,所以适合存储在代码段这种只读区域。当主程序加载DLL时,DLL的代码段被映射到主程序的地址空间中,这样主程序就可以通过对象的虚函数指针(vptr)访问到虚函数表。
  2. 虚函数表与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机制就利用虚函数表实现了运行时对象类型的识别。