跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ 虚函数表与虚指针详解

C++ 虚函数表(vtable)和虚指针(vptr)是实现多态的核心机制。vtable 存储虚函数地址,每个含虚函数的类生成一张;vptr 是对象内的隐藏指针,指向对应类的 vtable。动态绑定通过 vptr 定位 vtable 再调用函数实现。内存布局中 vptr 通常位于对象开头。重要细节包括只有虚函数入表、多继承可能多个 vptr、虚继承解决菱形问题、析构函数建议设为虚函数防止内存泄漏。

全栈工匠发布于 2026/3/15更新于 2026/6/227 浏览

一、虚函数表(vtable)

1. 定义
  • 虚函数表(vtable)是编译器为每个包含虚函数的类生成的一张表,本质上是一个数组,存储着该类所有虚函数的函数指针。
  • 虚表中存储了该类所有虚函数的地址,如果派生类重写了基类的虚函数,则派生类虚表中会替换为自身重写的函数地址;未重写的虚函数地址则继承自基类。
2. 特点
  • 每个含虚函数的 类 都会有一张虚表。
  • 继承关系:
    • 派生类会继承基类的虚表,但会根据自身重写的虚函数修改对应条目。
    • 如果派生类新增了虚函数,这些函数地址会被添加到虚表的末尾。
  • 虚表在 编译期确定,但调用时选择哪个表由对象的运行时类型决定。
  • 虚表通常存储在只读段(.rodata)中,不随对象复制而重复。
3. 示例
#include <iostream>
using namespace std;

class Base {
public:
    virtual void f1() { cout << "Base::f1\n"; }
    virtual void f2() { cout << "Base::f2\n"; }
    void f3() { cout << "Base::f3\n"; }
};

class Derived : public Base {
public:
    void f1() override //重写
    { cout << "Derived::f1\n"; }
    void f2() override //重写
    { cout << "Derived::f2\n"; }
    void f4() { cout << "Derived::f4\n"; }
};

编译器会生成:

  • Base 的虚表:{ &Base::f1, &Base::f2 }
    • 分析:其中基类成员函数 Base::f3 不是虚函数,因此该函数地址不会存在虚表中。
  • Derived 的虚表:{ &Derived::f1, &Derived::f2 }
    • 分析:派生类 Derived 重写了基类的虚函数,因此派生类 Derived 虚表中替换为自身重写的 Derived::f1 和 Derived::f2 函数地址。

二、虚指针(vptr)

1. 定义
  • 虚指针(vptr) 每个包含虚函数(或继承了虚函数)的类的对象,都会隐含一个指向虚表的成员指针,这个指针就是虚指针(vptr)。
  • vptr 通常位于对象内存布局的开头(具体位置由编译器决定),作为对象的隐藏成员存在。
2. 行为
  • 当对象构造时,编译器在构造函数里自动初始化 vptr,让它指向对应类的 vtable,因此类的构造函数不能是虚函数。
  • 如果是派生类对象,则在执行派生类构造函数时会更新 vptr 指向派生类的 vtable。
  • 调用虚函数时,编译器实际上做的是:
    1. 通过对象找到它的 vptr
    2. 通过 vptr 找到 vtable
    3. 从 vtable 中取出对应的函数指针
    4. 跳转执行
3. 调用流程伪代码

例如调用 b->f1()(b 是 Base*,但实际对象可能是 Derived):

b->vptr // 找到虚指针
->vtable[0] // 找到虚表的第一个函数地址
(b); // 调用该函数,传入 this 指针

三、内存布局示意

假设类如下:

class Base {
int x; // 普通数据成员
virtual void f(); // 虚函数
};

class Derived : public Base {
int y;
void f() override; // 覆盖
};

一个 Derived 对象的内存布局可能是(简化示意):

+-------------------+
| vptr -----------> |-----> vtable(Derived)
+-------------------+
| Base::x           |
+-------------------+
| Derived::y        |
+-------------------+

而 vtable(Derived) 内容可能是:

[0] &Derived::f 

四、重要细节

  1. 只有虚函数才进入虚表
    普通成员函数、静态函数不会放入虚表。
  2. 多继承
    • 如果一个类多继承多个有虚函数的基类,编译器可能为对象设置多个 vptr,每个基类一份。
  3. 虚继承
    • 在 多重继承 中可能会出现 菱形继承问题(diamond problem),导致派生类调用成员时产生二义性,使用虚继承可以解决该问题。
    • 在虚继承下,虚表更复杂,还会存储基类子对象的偏移量。
  4. 析构函数最好设为虚函数
    • 防止派生类对象没有执行自己的析构函数,导致内存泄漏。
    • 因为 delete basePtr; 时,如果 basePtr 实际指向派生类对象,只有虚析构才能确保调用派生类的析构函数。

五、总结

  • 虚表(vtable):类级别的函数指针表,存放虚函数地址。
  • 虚指针(vptr):对象级别的隐藏成员,指向该对象所属类的虚表。
  • 动态绑定过程:通过对象的 vptr → 定位 vtable → 取函数指针 → 调用。

目录

  1. 一、虚函数表(vtable)
  2. 1. 定义
  3. 2. 特点
  4. 3. 示例
  5. 二、虚指针(vptr)
  6. 1. 定义
  7. 2. 行为
  8. 3. 调用流程伪代码
  9. 三、内存布局示意
  10. 四、重要细节
  11. 五、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 Python 的币安期货交易机器人实战
  • Stable Diffusion 常用模型详解:Checkpoint、LoRA 与 ControlNet 等
  • 大模型微调(Fine-tuning)原理与实战指南
  • LangBot 企业级即时通讯 AI 机器人平台及 Space 账号注册指南
  • 结合腾讯云 HAI 与 DeepSeek 快速搭建个人网页
  • 双指针算法实战:移动零与复写零详解
  • 前端 SPA 分布式部署实践:基于 iframe 的微前端探索
  • 一切皆是映射:神经网络在物流优化中的实践案例
  • AI 大模型开发入门指南:学习路径与实战建议
  • GitHub Copilot 学生认证申请教程及配置步骤
  • Seedance 2.0 智能资源画像与 Terraform 算力预算方案实践
  • Vue Diff 算法详解:双端与快速 Diff 对比
  • 具身智能系统与 VLA 架构入门及实战
  • AI 绘画敏感内容提示词实战指南:从基础原理到安全实践
  • 基于 Q-Learning 的三维无人机动态避障路径规划 (MATLAB)
  • FPGA 摄像头采集处理显示指南:OV5640 到 HDMI 实时显示
  • 后仿真 SDF 反标常见 Warning 解析与处理方案
  • llama.cpp Docker 部署:容器化推理服务搭建
  • Transformer 模型架构详解与核心组件解析
  • Z-Image-Turbo 与 Stable Diffusion 实战对比:生成速度与质量分析

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online