Software Engineer · 语言与工程基础

C++ 虚函数分派:实际类型、override 与 ABI

解释基类引用如何找到派生实现,避免把 vtable 当语言唯一实现。

题目重点:解释基类引用如何找到派生实现,避免把 vtable 当语言唯一实现。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 以单继承示例讲语义,多继承和 ABI 布局作为追问,不假定固定内存偏移。

解题路线

  1. 虚调用按对象动态类型的最终覆写函数执行;override 让编译器检查签名匹配,避免 const 或参数误差造成隐藏。
  2. 常见实现用对象中的虚表指针查函数表,编译器也可能去虚化。标准规定行为,不要求所有实现都使用同一 vtable 布局。
  3. 按值把 Derived 复制到 Base 会切片,丢失派生部分;用引用或正确生命周期的指针保留多态。显式限定 Base::f 会抑制正常虚分派。
  4. 默认参数按调用处静态类型选取,虚函数体按动态类型选择。避免在覆写中设不同默认值,形成难懂组合。

手动走一遍

Base& b 指向 Derived,b.f 调 Derived::f;Base b2=derived 后,b2 只剩 Base 部分。基类 f(int x=1)、派生 f(int x=2),通过 Base 引用省略参数时派生函数可能收到1,而非2。

规模与取舍

常见间接调用开销不应一概量化;JIT/AOT 优化与缓存、分支预测有关,性能测真实调用形态。

易错点与追问

容易失分的边界

  • 所有带相同名字的函数都会覆写。
  • vtable 固定偏移作为可移植代码。
  • 忽略对象切片与生命周期。

继续深挖

  • 多继承为何可能需要 this 调整?
  • final 如何帮助表达设计和优化机会?

技术参考

✓已复制微信号!