override是C++11引入的强制性修饰符,用于显式声明重写基类虚函数,要求签名(含const等限定符)、返回类型协变、基类函数带virtual等完全匹配,否则编译报错,提升类型安全性。

override 关键字不是可选项,是编译器强制检查工具
它本身不改变行为,只告诉编译器:“我明确想重写基类虚函数”,一旦签名不匹配(比如参数类型差一个 const、返回类型协变没满足、或基类根本没这个虚函数),override 就会让编译直接报错,而不是静默变成新函数。
常见错误现象:g++ 报 error: 'xxx' does not override a base class member;或者更隐蔽的——函数没被调用,因为子类函数其实根本没重写成功,只是定义了个同名新函数。
- 必须和基类虚函数声明完全匹配(含
const、&、&&限定符) - 基类对应函数必须带
virtual(或来自override链上游),纯虚函数也适用 - 不能用于非虚函数、静态成员函数、构造/析构函数
- C++11 起支持,老项目若用 C++98 编译模式会直接编译失败
参数列表差一个 const 就算不匹配
这是最常踩的坑。比如基类是 virtual void draw() const,子类写成 void draw() 并加 override,编译器立刻拒绝——哪怕你只是忘了 const。
使用场景:GUI 组件、序列化接口、访问器函数等强调逻辑只读的场合,const 是语义一部分,不是可有可无的修饰。
立即学习“C++免费学习笔记(深入)”;
示例:
class Shape {
public:
virtual void render() const = 0;
};
class Circle : public Shape {
public:
void render() const override { /* ✅ 正确 */ }
// void render() override { /* ❌ 编译失败:缺少 const */ }
};返回类型协变要小心指针/引用层级
当重写返回指针或引用时,C++ 允许“协变”(covariant return type),但限制很具体:只能从基类指针/引用变为派生类指针/引用,且必须是同一继承链。
容易忽略的点:协变不适用于值类型、智能指针(std::unique_ptr 等需额外处理)、或跨继承体系的类型。
- 合法协变:
Base*→Derived*,Base&→Derived& - 非法:
Base*→int*,std::shared_ptr<Base>→std::shared_ptr<Derived>(需显式转换或模板特化) - 协变时仍需加
override,否则编译器无法验证是否真在重写
多继承下 override 可能触发二义性警告
如果两个基类都声明了同名虚函数(哪怕签名一致),子类用 override 实现时,编译器可能报 error: member 'xxx' overrides functions from multiple base classes。
这不是 bug,是提醒你:该函数到底属于哪个基类的接口?是否真需要同时满足两者语义?
- 解决方式通常是显式用作用域限定调用,或重构为虚继承+统一接口
- 别删掉
override去绕过警告——那等于放弃类型安全检查 - Clang 比 GCC 对这类情况更敏感,CI 上容易暴露
实际写的时候,override 最难的部分不是语法,是得真正理清继承意图:这个函数到底是扩展行为、替换实现,还是意外重名?漏掉它,问题可能拖到运行时才暴露;滥用它,编译就卡住。











