虚函数必须用virtual声明,否则静态绑定导致多态失效;含纯虚函数的类为抽象类;构造/析构中虚函数行为受限,基类析构函数必须virtual;子类重写须用override防错;vtable有微小开销但不应过早优化。

虚函数必须用 virtual 声明,否则调用走静态绑定
编译器看到非 virtual 成员函数,直接按指针/引用的**静态类型**决定调用哪个函数——哪怕实际对象是子类。这是最常踩的坑:写了继承、用了基类指针,但子类重写的函数就是不执行。
实操建议:
立即学习“C++免费学习笔记(深入)”;
-
virtual必须写在基类函数声明处(头文件中),子类重写时加不加virtual都行,但强烈建议加上,提高可读性 - 纯虚函数写成
virtual void func() = 0;,含纯虚函数的类就是抽象类,不能实例化 - 构造函数里不能依赖虚函数多态——此时子类部分还没构造,
virtual调用会降级为当前正在构造的类的版本
析构函数不加 virtual 会导致子类资源泄漏
如果基类指针指向子类对象,而基类析构函数不是 virtual,delete 时只调用基类析构函数,子类新增的成员(比如 new 出来的内存、打开的文件句柄)根本不会被清理。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 只要类设计为被继承(尤其有虚函数),基类析构函数必须声明为
virtual - 现代写法推荐用
virtual ~Base() = default;或virtual ~Base() {},避免隐式生成非虚析构 - 即使类没资源要释放,也别省这个
virtual——接口契约比“现在没资源”更重要
override 关键字不是可选修饰,是编译期防错刚需
不加 override,子类函数名拼错、参数类型差一个 const、返回值不协变,都会导致“以为重写了,其实只是新增了一个同名函数”,多态失效且毫无警告。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 子类所有意图重写的虚函数,后面必须跟
override - 编译器遇到
override但找不到匹配的基类虚函数,立刻报错,问题暴露在写代码时,而不是运行时行为异常 - 注意:C++11 起支持,确保编译器标准不低于
-std=c++11
虚函数表(vtable)带来间接调用开销,但别过早优化
每次通过指针/引用调用虚函数,都要查一次 vtable——一次内存读 + 一次跳转。相比普通函数调用,多了 1~2 个周期开销。但在绝大多数业务逻辑里,这微乎其微。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 性能敏感路径(如内循环、高频数学计算)若确定类型固定,可用模板或 final 类绕过虚调用
- 不要为“避免虚函数”把设计搞复杂:比如用
enum+switch模拟多态,维护成本和出错率远高于虚函数本身 -
final关键字可用于类或虚函数,告诉编译器“这里不可能再被继承/重写”,某些场景下能触发 devirtualization 优化
override 缺失这两处,问题往往延迟暴露,排查成本远高于预防成本。











