虚函数表(vtable)是编译器为含虚函数的类生成的静态只读函数指针数组,按声明顺序存储虚函数地址;对象通过首部vptr指向对应vtable,实现运行时动态绑定。
虚函数表(vtable)是C++实现运行时多态的核心机制,它是一张由编译器自动生成的函数指针数组,每个含虚函数的类都有且仅有一张vtable;对象内部隐含一个指向该表的指针(vptr),通过它在运行时决定调用哪个版本的虚函数。
vtable本质是一个静态的、只读的函数指针数组,按虚函数声明顺序排列。编译器在编译期为每个含虚函数的类生成一张vtable,内容包括:
ype_info指针(用于dynamic_cast和typeid)注意:普通成员函数、static函数、构造函数、析构函数(除非是虚析构)不进vtable;内联虚函数仍会出现在vtable中,只是调用时可能被优化。
每个含虚函数的类的对象,在内存最前面(x86/x64下通常是前8字节)隐式存储一个vptr,指向其所属类的vtable。例如:
class Base { virtual void f() {} };
class Derived : public Base { void f() override {} };那么:
– Base b; 的 vptr 指向 Base 的 vtable,其中 f() 地址是 Base::f
– Derived d; 的 vptr 指向 Derived 的 vtable,其中 f() 地址是 Derived::f
– Base* p = new Derived; 中 p 实际指向 d,p->f() 会通过 d 的 vptr 找到 Derived::f —— 这就是动态绑定的关键。
当你写下 ptr->func()(func 是虚函数),实际执行流程是:
这解释了为什么 Base* p = new Derived 能调用 Derived::func:真正起作用的是对象本身的 vptr,不是指针类型。
• 构造函数里调用虚函数不会多态:因为此时 vptr 正在被逐层初始化(先设为 Base vtable,再改为 Derived vtable),尚未完全就绪。
• 虚析构函数必须存在:否则 delete Base* 可能只调 Base 析构,漏掉 Derived 部分 —— vtable 确保了析构链正确触发。
• 空类或只有非虚函数的类没有 vptr,sizeof 可能为 1;一旦加 virtual,即使无数据成员,sizeof 至少为指针大小(如8字节)。
• 多重继承下 vptr 可能不止一个(不同基类子对象各带自己的 vptr),vtable 结构更复杂,但原理不变。
基本上就这些。vtable 不神秘,它是编译器悄悄铺好的一张路由表,让“同一个调用”在不同对象上走向不同的实现 —— 多态的本质,就是运行时查表跳转。
# 字节
# c++
# 路由
# 排列
# 为什么
# Static
# 多态
# 成员函数
# 构造函数
# 析构函数
# 指针
# 继承
# 虚函数
# 指针类型
# 多重继承
# delete
# 对象
# 它是
# 跳转
# 绑定
# 自己的
# 的是
# 是一个
# 几个
# 都有
# 这就是
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化76771 】
【
技术知识130152 】
【
IDC云计算60162 】
【
营销推广131313 】
【
AI优化88182 】
【
百度推广37138 】
【
网站推荐60173 】
【
精选阅读31334 】
相关推荐:
Python项目维护经验_长期演进说明【指导】
Python字符串操作教程_切片拼接与格式化详解
Win11怎么设置任务栏透明_Windows11使用工具美化任务栏
Windows10如何更改计算机工作组_Win10系统属性修改Workgroup
C++如何解析JSON数据?(nlohmann/json库示例)
MAC如何修改默认应用程序_MAC文件后缀关联设置与打开方式更改【教程】
如何在 Go 后端安全获取并验证前端存储的 JWT?
Win11怎么设置虚拟键盘_打开Win11屏幕键盘操作指南【技巧】
Go 中的 := 运算符:类型推导机制与使用边界详解
Python与OpenAI接口集成实战_生成式AI应用场景解析
php增删改查需要哪些扩展_开启mysqli或pdo扩展方法【说明】
C++ static_cast和dynamic_cast区别_C++静态转换与动态类型安全转换
Win11怎么更改鼠标指针_Windows 11自定义鼠标样式与大小【美化】
Mac如何设置动态壁纸?(让桌面动起来)
Windows10如何更改盘符名称_Win10重命名硬盘分区卷标
Python文件和流处理指南_高效读写大体积数据文件
PHP 中如何在函数内持久化修改引用变量的指向
如何使用Golang读取日志文件_Golang bufio Scanner日志处理示例
Mac的Time Machine怎么用_Mac系统备份与数据恢复【完整指南】
如何用::实现工具类方法调用_php静态工具类设计技巧【技巧】
Win11怎么设置触控板手势_Windows11三指四指操作自定义
如何使用Golang处理静态文件缓存_提高页面加载速度
如何在Golang中处理URL参数_Golang URL参数解析与路由映射方法
如何在包含多值的列中精准搜索指定演员?
mac怎么右键_MAC鼠标右键设置与触控板手势技巧【入门】
c++怎么实现大文件的分块读写_c++ 文件指针seekp与seekg偏移控制【方法】
Python路径拼接规范_跨平台处理说明【指导】
Win11如何设置系统语言_Win11系统语言切换教程【攻略】
如何自定义Windows终端的默认配置文件?(PowerShell/CMD)
Python迭代器生成器进阶教程_节省内存与懒加载实战
windows 10专注助手怎么关闭_windows 10禁用通知提醒功能方法
Win11怎么设置屏保_Windows 11屏幕保护程序开启与设置【详解】
C#如何序列化对象为XML XmlSerializer用法
Win11如何添加/删除输入法 Win11切换中英文输入法快捷键【设置】
Windows服务启动类型恢复方法_错误修改导致的系统服务异常
Win11用户账户控制怎么关_Win11关闭UAC弹窗提示【设置】
如何在 Go 中高效缓存与分发网络视频流
Windows10如何更改桌面背景_Win10个性化幻灯片放映设置
Win11局域网共享怎么设置 Win11文件夹网络共享教程【详解】
LINUX怎么查看进程_LINUX ps命令查看运行服务
Mac上的iMovie如何剪辑视频?(新手入门教程)
Windows 10怎么把任务栏放在屏幕上方_Windows 10解锁任务栏并拖动位置
Win11怎么开启窗口对齐助手_Windows11系统多任务处理设置
Win10怎样卸载DockerDesktop_Win10卸载DockerDesktop步骤【步骤】
Win11色盲模式怎么开_Win11屏幕颜色滤镜设置【关怀】
Go 语言标准库为何不提供泛型切片的 Contains 方法?
Win11怎么设置开机自动连接宽带_Windows11创建拨号连接计划任务
C++如何使用std::async进行异步编程?(future用法)
Windows10如何彻底关闭自动更新_Win10服务与组策略双重禁用
PythonPandas数据分析教程_数据清洗与处理技巧
2025-12-20
致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。