override用于显式声明重写虚函数,强制编译器检查签名匹配;final用于禁止继承或进一步重写,二者均为C++11引入的编译期约束关键字。
override 用来明确表示重写虚函数
不加 override 时,编译器不会检查你是否真的重写了父类虚函数。比如参数类型写错、const 修饰不一致、返回类型协变没处理好,都会悄悄变成新函数(重载),而不是重写——结果就是多态调用不生效,bug 很难发现。
加上 override 后,编译器强制校验:必须存在可访问的、签名匹配的虚函数在基类中,否则直接报错,错误信息通常是 error: 'func' does not override any member functions。
- 只能用于成员函数声明(定义里不能写)
- 必须和基类虚函数的 const/volatile/ref-qualifier 完全一致
- 返回类型需满足协变规则(如基类返回
Base*,派生类可返回Derived*) - 不能用于非虚函数,也不能用于构造/析构/重载运算符(除非它们本身是虚的)
示例:
struct Base {
virtual void foo(int) const;
virtual ~Base() = default;
};
struct Derived : Base {
void foo(int) const override; // ✅ 正确
void foo(double) const override; // ❌ 编译失败:基类没有这个签名
void bar() const override; // ❌ 编译失败:Base 没有虚函数 bar
};
final 阻止进一步继承或重写
final 是个“终止符”,有两个作用位置:类名后阻止继承,函数声明后阻止重写。它不改变语义,只加编译期限制,一旦违反就报错,比如 error: cannot derive from 'final' base class 或 error: function 'f' marked 'final' cannot be overridden。
立即学习“C++免费学习笔记(深入)”;
- 写在类定义末尾:
struct X final { ... };→ 其他类不能class Y : X {} - 写在虚函数声明末尾:
virtual void f() final;→ 派生类不能再override它 -
final和override可以一起用:void f() override final;,表示“我重写了,且到此为止” - 不能用在非虚函数、非成员函数、模板声明上
典型场景:想封装一个策略类,允许用户继承一次实现定制逻辑,但禁止继续派生以防误用;或某个关键虚函数逻辑已固化,不允许下游修改。