MST

星途 面试题库

面试题:C++ 中虚函数表指针的初始化时机

在 C++ 中,虚函数表指针(vptr)在什么时候被初始化?请详细说明不同类型对象(如普通类对象、派生类对象)的虚函数表指针初始化情况。
37.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

虚函数表指针(vptr)初始化时机

  1. 普通类对象
    • 当一个类中包含虚函数时,该类的对象会有一个虚函数表指针(vptr)。在对象构造时,vptr 会被初始化。具体来说,在构造函数执行过程中,在进入用户代码之前,编译器会将 vptr 指向该类对应的虚函数表。
  2. 派生类对象
    • 单继承情况
      • 派生类对象构造时,首先调用基类构造函数。在基类构造函数执行过程中(进入基类构造函数用户代码前),vptr 会被初始化为指向基类的虚函数表。
      • 然后执行派生类构造函数,在派生类构造函数执行过程中(进入派生类构造函数用户代码前),vptr 会被重新初始化为指向派生类的虚函数表。如果派生类没有重写基类的虚函数,派生类虚函数表中的对应函数指针仍指向基类虚函数的实现;若派生类重写了虚函数,则虚函数表中对应函数指针指向派生类重写后的函数实现。
    • 多继承情况
      • 当派生类从多个基类继承(多继承)且这些基类有虚函数时,派生类对象可能会有多个 vptr(每个有虚函数的基类对应一个 vptr)。
      • 构造派生类对象时,按照继承列表顺序依次调用基类构造函数。每个基类构造函数执行时(进入基类构造函数用户代码前),会初始化对应的 vptr 指向该基类的虚函数表。
      • 最后执行派生类构造函数,在派生类构造函数执行过程中(进入派生类构造函数用户代码前),会对相关 vptr 进行调整,使其正确指向派生类对应的虚函数表(可能存在覆盖基类虚函数的情况)。如果派生类没有重写某个基类的虚函数,对应虚函数表中的函数指针仍指向基类虚函数的实现;若重写了,则指向派生类重写后的函数实现。
    • 菱形继承情况(多继承的一种特殊情况)
      • 菱形继承下,若基类有虚函数,派生类对象同样会有多个 vptr 相关情况。构造过程较为复杂,在构造派生类对象时,先构造虚基类子对象,在虚基类构造函数执行过程中(进入虚基类构造函数用户代码前)初始化其对应的 vptr。然后按照继承列表顺序构造其他非虚基类子对象,同样在其构造函数执行过程中(进入非虚基类构造函数用户代码前)初始化对应的 vptr。最后执行派生类构造函数,会对所有 vptr 进行调整,以正确反映派生类的虚函数情况,包括虚函数的重写等。