C++中虚函数表的初始化时机
虚函数表(vtable)的初始化时机 谈到C++虚函数表的初始化,很多人觉得玄乎,其实拆开看就两个阶段:一个是编译/链接期干的事,一个是运行期干的事。分工非常明确,搞清楚了,多态那点底子也就透了。 编译/链接期:vtable 结构的确定(静态阶段) 当你写一个带虚函数的类,比如 class A {
虚函数表(vtable)的初始化时机
谈到C++虚函数表的初始化,很多人觉得玄乎,其实拆开看就两个阶段:一个是编译/链接期干的事,一个是运行期干的事。分工非常明确,搞清楚了,多态那点底子也就透了。

编译/链接期:vtable 结构的确定(静态阶段)
当你写一个带虚函数的类,比如 class A { virtual void f(); },然后编译它——编译器会做什么?它会为每个包含虚函数的类(或者从虚函数类继承下来的子类)生成一份固定的 vtable 数据结构。说白了,就是一个函数指针数组,里面填好了各个虚函数的地址,比如 A::f 的地址。
这份 vtable 会被编译到程序的只读数据段(.rodata)里,跟代码段一样,属于程序启动之前就已经确定好的“静态数据”。也就是说,类的虚函数表本身不是运行时捏出来的,而是编译期就焊死在二进制里的。
运行期:vptr(虚函数表指针)的初始化(动态阶段)
每个包含虚函数的对象,内部都藏着一个隐藏的 vptr 成员,它的作用就是指向所属类的那个 vtable。这个指针什么时候初始化?
- 对于普通对象:
vptr在构造函数执行的最开始阶段完成初始化——注意,早于构造函数的函数体。也就是说,构造函数体还没跑,vptr 已经指向了正确的 vtable。子类构造时,会先初始化父类的vptr,再切换到子类自己的vptr。 - 对于全局/静态对象:
vptr在程序启动后的全局初始化阶段(main 函数执行前)完成。 - 对于 new 创建的对象:
vptr在operator new分配内存之后、构造函数执行之前初始化。
一句话总结:vtable 是静态的,vptr 才是动态的,真正实现多态靠的是指针的切换。
验证代码(C++)
#includeusing 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,所以同一个对象在不同构造阶段调用虚函数,走的是不同的版本。
常见误区
- ❌ 错误:每次创建对象都会生成新的 vtable。
✅ 正解:一个类就一份 vtable(编译期确定的),所有对象的vptr都指向同一张表,不会重复创建。 - ❌ 错误:vptr 在构造函数体执行后初始化。
✅ 正解:vptr初始化是在构造函数的“初始化列表阶段”(编译器自动插入的),早于函数体。所以构造函数体里调虚函数,已经能正确分发。 - ❌ 错误:虚函数表在运行时动态生成。
✅ 正解:vtable 本身是编译期生成的静态数据,存在只读段里。运行时只初始化vptr指向它,表本身不动。
总结
- 虚函数表(vtable)本身:编译/链接期生成,存在只读数据段,一个类只有一份,全局唯一。
- 虚函数表指针(vptr):运行期初始化,普通对象在构造函数执行前完成,子类构造时覆盖父类的
vptr。 - 核心逻辑:vtable 是“静态模板”,vptr 是“动态指针”,二者结合,多态就成了。
Postman是一套面向API全生命周期的开发与测试平台,可在Mac上发送和调试多种协议请求,管理集合、环境及认证信息,并完成脚本测试、模拟服务、监控、文档发布和团队协作。它适合开发、测试及运维人员使用,提供个人免费方案。
Docker Desktop 是 Docker 官方为 Mac 提供的容器开发环境,集成 Docker Engine、命令行工具、Compose、Build、Kubernetes 与图形化管理界面。
Android Studio 是 Google 面向安卓应用开发提供的官方集成开发环境,基于 IntelliJ IDEA 构建。它整合智能代码编辑、Gradle 构建、界面预览、设备模拟、性能分析、调试测试及 APK 分析等工具。
PixPix 是面向品牌、卖家和内容团队的在线 AI 图片视频创作平台,提供图视频 Agent、无限画布、图片生成、视频生成、自然语言编辑及商品套图、产品精修和带货视频等电商工具。
Postman 是面向 API 全生命周期的开发与协作平台。Windows 桌面版可用于构建和发送 HTTP、GraphQL、gRPC、WebSocket、MQTT 等请求,并提供环境变量、集合、脚本测试、模拟服务、监控、文档及团队工作区等
Docker Desktop 为 Windows 开发者提供集成式容器环境,内置 Docker Engine、命令行工具、Compose、Build 与 Kubernetes 等组件,可在本机完成镜像构建、容器运行、日志查看和资源管理。













