C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++虚函数表初始化

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

作者:OxyTheCrack

虚函数表初始化分为编译期和运行期两个阶段,本文就来详细的介绍一下C++中虚函数表的初始化时机,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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

虚函数表的初始化分为两个阶段,一个是编译/链接期,一个是运行期,二者分工不同:

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

编写包含虚函数的类(比如 class A { virtual void f(); })并编译时:

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

每个包含虚函数的对象,都会有一个隐藏的 vptr 成员(指向所属类的 vtable),这个指针的初始化:

验证代码(C++)

#include <iostream>
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 都指向这份 vtable。
  2. ❌ 错误:“vptr 在构造函数体执行后初始化”
    ✅ 正确:vptr 初始化在构造函数的“初始化列表阶段”(编译器自动插入),早于函数体执行。
  3. ❌ 错误:“虚函数表在运行时动态生成”
    ✅ 正确:vtable 本身是编译期生成的静态数据,运行时只初始化 vptr 指向它。

总结

  1. 虚函数表(vtable)本身:编译/链接期生成,存储在只读数据段,属于类的静态资源,全局唯一。
  2. 虚函数表指针(vptr):运行期初始化,普通对象在构造函数执行前完成,子类构造时会覆盖父类的 vptr。
  3. 核心逻辑:vtable 是“静态模板”,vptr 是“动态指针”,二者结合实现多态。

到此这篇关于C++中虚函数表的初始化时机的文章就介绍到这了,更多相关C++虚函数表初始化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文