题目重点:解释基类引用如何找到派生实现,避免把 vtable 当语言唯一实现。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 以单继承示例讲语义,多继承和 ABI 布局作为追问,不假定固定内存偏移。
解题路线
- 虚调用按对象动态类型的最终覆写函数执行;override 让编译器检查签名匹配,避免 const 或参数误差造成隐藏。
- 常见实现用对象中的虚表指针查函数表,编译器也可能去虚化。标准规定行为,不要求所有实现都使用同一 vtable 布局。
- 按值把 Derived 复制到 Base 会切片,丢失派生部分;用引用或正确生命周期的指针保留多态。显式限定 Base::f 会抑制正常虚分派。
- 默认参数按调用处静态类型选取,虚函数体按动态类型选择。避免在覆写中设不同默认值,形成难懂组合。
手动走一遍
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 如何帮助表达设计和优化机会?
技术参考
- C++ 虚函数语义:技术语义参考,具体题目按本文约定。
