C++ 怎么实现多态 C++虚函数与动态绑定机制详解【面试】
发布时间 - 2026-01-27 00:00:00 点击率:次基类指针调用虚函数时执行派生类版本,因编译器生成vtable并由对象vptr在运行时动态绑定;须通过指针或引用调用且函数声明为virtual,否则静态绑定。
为什么基类指针调用函数时,实际执行的是派生类的版本
因为编译器在遇到 virtual 声明的函数时,会为该类生成虚函数表(vtable),每个对象头部隐式存储一个指向该表的指针(vptr)。运行时通过 vptr 找到对应函数地址,完成动态绑定。
关键前提是:必须通过指针或引用调用,且函数声明为 virtual。直接用对象值传递会触发静态绑定(即切片 + 编译期决议)。
- 非
virtual函数:编译期根据变量静态类型决定调用哪个版本 -
virtual函数:运行期根据对象实际类型查 vtable 决定调用哪个版本 - 构造函数不能是
virtual;析构函数建议声明为virtual(尤其基类有指针成员时)
虚函数表(vtable)在内存中长什么样
vtable 是编译器生成的静态数组,每个元素是函数指针,顺序与类中 virtual 函数声明顺序一致。单继承下,派生类 vtable 会复制基类部分,并覆盖被重写的函数地址;多继承则可能有多个 vptr,布局更复杂。
注意:vtable 不是对象的一部分,而是类级别的只读数据;vptr 才是每个对象开头的指针(通常 8 字节,在 64 位系统上)。
- 可以用
sizeof验证:带虚函数的类,即使无成员变量,sizeof也至少
为 8
- gdb 中可打印
*((void**)obj)查看 vptr 指向的首项(即第一个虚函数地址) - 纯虚函数在 vtable 中对应 nullptr,强制子类实现
override 和 final 关键字到底防什么
override 不是语法糖,它让编译器检查:当前函数是否真的重写了基类的 virtual 函数。拼错函数名、参数不匹配、const 修饰不一致都会报错。
final 则禁止后续派生类再重写该函数,或禁止整个类被继承。两者都用于把本应在运行时暴露的问题(如意外未重写、误覆写)提前到编译期捕获。
- 没加
override时,看似重写成功,实则定义了一个新函数,基类虚函数仍按原逻辑走 - 基类函数加了
final,子类里再写同签名函数并加override,编译直接失败 - 函数参数类型用引用/指针时,顶层 const 不影响重写判断;但底层 const(如
int* const)会影响
动态绑定失效的典型场景
最常见的是在构造函数和析构函数内部调用虚函数——此时动态绑定不生效,调用的是当前正在构造/析构的那个类的版本,而非最终派生类的版本。
原因:对象的 vptr 在构造函数执行过程中逐步被修改(先设为基类 vtable 地址,再逐层更新),析构时则逆向还原。所以中间状态无法反映完整类型。
- 构造函数中调用
virtual函数,等价于调用当前类的函数(哪怕派生类已重写) - 析构函数中同理,不会跳转到派生类实现
- 避免在构造/析构中做依赖多态的行为;如需初始化逻辑,可提取为独立的
init()并由用户显式调用
虚函数机制本身开销很小(一次指针解引用 + 偏移寻址),但真正容易出问题的地方,往往不是“怎么写”,而是“在哪调”和“谁来管生命周期”。尤其是跨模块传递对象、用智能指针管理多态对象时,vptr 的存在和析构顺序会直接影响行为是否符合预期。
# 字节
# c++
# 为什么
# 多态
# 成员变量
# 子类
# 构造函数
# 析构函数
# const
# 引用调用
# int
# void
# 指针
# 继承
# 多继承
# 虚函数
# 纯虚函数
# 值传递
# 切片
# 对象
# 重写
# 绑定
# 派生类
# 的是
# 并由
# 或引用
# 是在
# 第一个
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何正确下载安装西数主机建站助手?
Javascript中的事件循环是如何工作的_如何利用Javascript事件循环优化异步代码?
如何在宝塔面板创建新站点?
Win11关机界面怎么改_Win11自定义关机画面设置【工具】
Laravel Telescope怎么调试_使用Laravel Telescope进行应用监控与调试
如何确认建站备案号应放置的具体位置?
大连 网站制作,大连天途有线官网?
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案
如何制作一个表白网站视频,关于勇敢表白的小标题?
php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】
Laravel观察者模式如何使用_Laravel Model Observer配置
教学论文网站制作软件有哪些,写论文用什么软件
?
Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程
详解Oracle修改字段类型方法总结
Laravel如何为API生成Swagger或OpenAPI文档
网站制作软件免费下载安装,有哪些免费下载的软件网站?
如何在服务器上三步完成建站并提升流量?
HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】
Laravel如何正确地在控制器和模型之间分配逻辑_Laravel代码职责分离与架构建议
长沙企业网站制作哪家好,长沙水业集团官方网站?
如何在 Go 中优雅地映射具有动态字段的 JSON 对象到结构体
Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】
Laravel如何与Vue.js集成_Laravel + Vue前后端分离项目搭建指南
详解jQuery停止动画——stop()方法的使用
如何获取PHP WAP自助建站系统源码?
Laravel怎么设置路由分组Prefix_Laravel多级路由嵌套与命名空间隔离【步骤】
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
佐糖AI抠图怎样调整抠图精度_佐糖AI精度调整与放大细化操作【攻略】
HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】
Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)
网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?
个人摄影网站制作流程,摄影爱好者都去什么网站?
Linux系统运维自动化项目教程_Ansible批量管理实战
HTML透明颜色代码在Angular里怎么设置_Angular透明颜色使用指南【详解】
如何快速配置高效服务器建站软件?
Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康
jQuery validate插件功能与用法详解
什么是javascript作用域_全局和局部作用域有什么区别?
如何挑选最适合建站的高性能VPS主机?
如何在Ubuntu系统下快速搭建WordPress个人网站?
Windows10如何删除恢复分区_Win10 Diskpart命令强制删除分区
如何自定义建站之星模板颜色并下载新样式?
PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)
香港服务器租用每月最低只需15元?
,在苏州找工作,上哪个网站比较好?
千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】
如何用AI帮你把自己的生活经历写成一个有趣的故事?
如何快速选择适合个人网站的云服务器配置?
Laravel如何自定义分页视图?(Pagination示例)


