讲师中心 微信公众号

工具推荐

视频效率加速
剧云
剧云

中文短剧剧本制作平台

Seko
Seko

AI短剧一键生成成片

updream

一键生成高质量推广成片

AniShort
AniShort

AI短剧协同制作平台

c++的虚函数表(vtable)是如何工作的? (深入理解多态)

浅涛大大_1596

浅涛大大_1596

发布时间:2026-01-11 12:35:33

|

728人浏览过

|

来源于php中文网

原创

虚函数表指针(vptr)始终位于对象内存起始处,指向编译期生成的虚函数表(vtable);vtable按虚函数声明顺序存储函数指针,构造/析构中vptr动态更新以保障正确多态调用。

c++的虚函数表(vtable)是如何工作的? (深入理解多态)

虚函数表指针(vptr)在对象内存布局中的位置

每个含有虚函数的类,编译器会在其对象的最开始处隐式插入一个 vptr(虚函数表指针),指向该类的虚函数表(vtable)。这个指针大小取决于平台(通常是 8 字节在 64 位系统上),且**永远位于对象内存的起始地址**。

这意味着:sizeof 一个含虚函数的类,一定 ≥ 指针大小;即使类中只有虚函数、无成员变量,sizeof 也不为 0。

  • 派生类对象也包含自己的 vptr,但若未重写基类虚函数,则对应表项仍指向基类实现
  • 多重继承时,子对象可能有多个 vptr(例如每个虚基类子对象一份),布局更复杂,但主流编译器(如 GCC、MSVC)通常只在最派生对象开头放一个主 vptr,其余通过偏移调整
  • 注意:vptr 是编译器自动维护的,无法在 C++ 源码中直接访问或修改;尝试用 reinterpret_cast 强转取址属于未定义行为

虚函数表(vtable)的内容与生成时机

vtable 是编译期生成的静态数组,每个类(而非每个对象)一份,存储的是函数指针(void (*)() 类型),按虚函数声明顺序排列。纯虚函数在表中存为 nullptr 或特定陷阱地址(如 GCC 填 __cxa_pure_virtual)。

关键点:

立即学习“C++免费学习笔记(深入)”;

  • 构造函数中,对象的 vptr 会被逐步设置:先设为基类 vtable 地址,进入派生类构造函数后才更新为派生类 vtable
  • 因此,在基类构造函数里调用虚函数,实际执行的是基类版本——哪怕派生类已重写,此时 vptr 还没被改写
  • 析构同理:析构顺序与构造相反,vptr 逐层回退,确保调用对应层级的虚函数

多态调用如何通过 vtable 实现(以 g++ 为例)

当通过基类指针或引用调用虚函数时,CPU 执行流程是:取对象首地址 → 解引用 vptr 得到 vtable 起始地址 → 按虚函数在类中声明顺序计算偏移(如第 0 个是 func1,则取 vtable[0])→ 调用该地址处的函数。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

示例代码可验证这一机制:

#include <iostream>
struct Base {
    virtual void f() { std::cout << "Base::f\n"; }
    virtual void g() { std::cout << "Base::g\n"; }
};
struct Derived : Base {
    void f() override { std::cout << "Derived::f\n"; }
};
int main() {
    Derived d;
    // 强制读取 vptr(仅用于演示,非标准做法)
    void** vptr = *static_cast<void***>(&d);
    std::cout << "vtable addr: " << vptr << "\n";
    // 调用 vtable[0](即 f())
    using Func = void(*)();
    Func f_ptr = reinterpret_cast<Func>(vptr[0]);
    f_ptr(); // 输出 "Derived::f"
}

注意:reinterpret_cast 访问 vtable 是非便携、非标准行为,仅用于教学观察;实际项目中绝不应依赖此方式。

虚函数调用的性能开销与优化边界

相比普通函数调用,虚函数多一次内存加载(从对象取 vptr)+ 一次间接跳转(查 vtable + call),现代 CPU 的分支预测器通常能很好处理这种规律性跳转,所以开销极小(通常就几个周期)。

但以下情况会破坏可预测性,导致性能下降:

  • 热路径中频繁切换不同子类对象(vtable 地址变化大,vptr 加载后缓存局部性差)
  • 虚函数内联失败:编译器无法在编译期确定目标函数,故不内联(除非启用 LTO + 全局分析)
  • 启用了控制流完整性(CFI)等安全机制时,间接调用需额外验证,开销上升

真正影响性能的往往不是 vtable 查找本身,而是虚函数常伴随动态内存分配、缓存不友好访问模式等副作用。别过早优化 vtable,先确认它真是瓶颈。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

函子Zion

一款支持AI搭建、可视化编辑和多端发布的全栈无代码开发平台。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

相关专题

更多
java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

375

2025.11.27

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

636

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

391

2025.11.27

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

399

2026.04.23

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

20

2026.11.12

Go-Zero安装与goctl环境配置教程
Go-Zero安装与goctl环境配置教程

本专题围绕Go-Zero的安装与工具链配置展开,讲清Go版本要求、goctl安装方式、代理镜像、protoc依赖与环境变量设置,说明多版本共存、升级回退与CI流水线安装的做法,并整理安装阶段的常见报错与验证步骤。

20

2026.11.12

Go-Zero零基础入门教程
Go-Zero零基础入门教程

本专题整理Go-Zero的入门知识,从框架定位、环境准备到跑通第一个API服务,讲清目录分层、配置加载、日志与中间件的基本用法,并对比Gin、Kratos的差异,帮助Go开发者建立整体认知,判断它是否适合当前项目。

20

2026.11.12

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

120

2026.11.06

Postman请求头Headers怎么设置
Postman请求头Headers怎么设置

围绕Postman HTTP请求头配置展开,讲解Headers选项的具体使用方式,包括Key和Value参数填写、请求头信息添加、常见Header字段设置及请求头修改方法,帮助用户解决接口调试过程中遇到的请求头配置问题。

100

2026.11.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn