商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C++中虚函数表的初始化时机

C++中虚函数表的初始化时机

  发布于2026-07-24 阅读(0)

扫一扫,手机访问

虚函数表(vtable)的初始化时机

谈到C++虚函数表的初始化,很多人觉得玄乎,其实拆开看就两个阶段:一个是编译/链接期干的事,一个是运行期干的事。分工非常明确,搞清楚了,多态那点底子也就透了。

C++中虚函数表的初始化时机

编译/链接期:vtable 结构的确定(静态阶段)

当你写一个带虚函数的类,比如 class A { virtual void f(); },然后编译它——编译器会做什么?它会为每个包含虚函数的类(或者从虚函数类继承下来的子类)生成一份固定的 vtable 数据结构。说白了,就是一个函数指针数组,里面填好了各个虚函数的地址,比如 A::f 的地址。

这份 vtable 会被编译到程序的只读数据段(.rodata)里,跟代码段一样,属于程序启动之前就已经确定好的“静态数据”。也就是说,类的虚函数表本身不是运行时捏出来的,而是编译期就焊死在二进制里的。

运行期:vptr(虚函数表指针)的初始化(动态阶段)

每个包含虚函数的对象,内部都藏着一个隐藏的 vptr 成员,它的作用就是指向所属类的那个 vtable。这个指针什么时候初始化?

  • 对于普通对象vptr 在构造函数执行的最开始阶段完成初始化——注意,早于构造函数的函数体。也就是说,构造函数体还没跑,vptr 已经指向了正确的 vtable。子类构造时,会先初始化父类的 vptr,再切换到子类自己的 vptr
  • 对于全局/静态对象vptr 在程序启动后的全局初始化阶段(main 函数执行前)完成。
  • 对于 new 创建的对象vptroperator new 分配内存之后、构造函数执行之前初始化。

一句话总结:vtable 是静态的,vptr 才是动态的,真正实现多态靠的是指针的切换。

验证代码(C++)

#include 
using namespace std;

class Base {
public:
    Base() {
        // 此时 vptr 已经指向 Base 的 vtable,调用虚函数会走 Base 版本
        func(); // 输出 "Base::func"
    }
    virtual void func() { cout << "Base::func" << endl; }
};

class Derived : public Base {
public:
    Derived() {
        // 此时 vptr 已经切换到 Derived 的 vtable
        func(); // 输出 "Derived::func"
    }
    void func() override { cout << "Derived::func" << endl; }
};

int main() {
    Derived d; 
    // 构造过程:
    // 1. 初始化 Base 部分 → vptr 指向 Base::vtable → 调用 Base::func
    // 2. 初始化 Derived 部分 → vptr 切换到 Derived::vtable → 调用 Derived::func
    return 0;
}

输出结果

Base::func

Derived::func

代码跑出来很清楚:vptr 在构造函数执行时已经就位,而且子类构造时会覆盖父类的 vptr,所以同一个对象在不同构造阶段调用虚函数,走的是不同的版本。

常见误区

  1. ❌ 错误:每次创建对象都会生成新的 vtable。
    ✅ 正解:一个类就一份 vtable(编译期确定的),所有对象的 vptr 都指向同一张表,不会重复创建。
  2. ❌ 错误:vptr 在构造函数体执行后初始化。
    ✅ 正解:vptr 初始化是在构造函数的“初始化列表阶段”(编译器自动插入的),早于函数体。所以构造函数体里调虚函数,已经能正确分发。
  3. ❌ 错误:虚函数表在运行时动态生成。
    ✅ 正解:vtable 本身是编译期生成的静态数据,存在只读段里。运行时只初始化 vptr 指向它,表本身不动。

总结

  1. 虚函数表(vtable)本身:编译/链接期生成,存在只读数据段,一个类只有一份,全局唯一。
  2. 虚函数表指针(vptr):运行期初始化,普通对象在构造函数执行前完成,子类构造时覆盖父类的 vptr
  3. 核心逻辑:vtable 是“静态模板”,vptr 是“动态指针”,二者结合,多态就成了。
本文转载于:https://www.jb51.net/program/367992pq4.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注