override关键字是强制编译器校验虚函数重写的必要修饰符,若子类函数签名与基类虚函数不严格匹配(如const、引用限定符、返回类型协变等),不加override将静默定义新函数而非重写,导致多态失效。

override 关键字不是可有可无的修饰符
它强制编译器检查:你写的这个函数,是否真正在基类中存在对应的虚函数声明。如果没有匹配的虚函数,override 会直接报错,而不是静默忽略或意外调用父类实现。
常见错误现象:void func() override 编译失败,提示“no function declared in base class”,但你不加 override 却能编译通过——结果是定义了一个新函数,而非重写,多态调用时根本不会走你写的版本。
使用场景:所有明确想重写虚函数的地方都该加 override,尤其是继承链较深、接口较多时。它本质是“契约校验”,不是语法糖。
不加 override 可能导致运行时行为完全错误
虚函数调用依赖动态绑定,但前提是子类函数签名(包括 const、引用限定符、返回类型协变)必须严格匹配基类声明。漏掉一个 const 或参数类型差一个 &,就不算重写。
立即学习“C++免费学习笔记(深入)”;
容易踩的坑:
- 基类函数是
virtual void draw() const,子类写成void draw()—— 不加override时不报错,但调用ptr->draw()时可能调用基类实现,甚至触发未定义行为 - 返回类型没满足协变要求(如基类返回
Base*,子类返回Derived*),但忘了加override,编译器不会提醒 - 参数是
std::string_view,基类是const std::string&—— 类型不兼容,不算重写,不加override就悄悄变成重载
override 和 virtual 不能互相替代
virtual 是在基类中声明“我允许被重写”,override 是在派生类中声明“我明确要重写某个虚函数”。两者语义不同,位置不同,作用不可互换。
关键区别:
- 派生类函数加
virtual不代表它被重写了;没加override就没有校验机制 - 派生类函数只加
override不加virtual是合法且推荐的(C++11 起),因为重写函数自动具有虚特性 - 同时写
virtual override合法但冗余,override已隐含虚性
性能 / 兼容性影响:无。它纯属编译期检查,生成的代码和手写虚函数表完全一致,不影响运行时开销。
现代 C++ 项目里不写 override 基本等于放弃类型安全
它不是“锦上添花”,而是防止低级但致命错误的第一道防线。尤其在团队协作或重构时,基类接口微调(比如加个 const)很容易让下游重写失效,而 override 能立刻暴露问题。
容易被忽略的一点:模板类中的虚函数重写也必须用 override,否则特化版本极易因签名偏差而失效,且编译器很难给出清晰提示。









