override关键字用于显式声明重写虚函数,强制编译器检查签名一致性(含const、ref-qualifier、参数类型、返回类型协变等),不匹配则报错,提升编译期安全性。
它不是语法必需的,但能强制编译器检查:你写的函数是否真的在基类中存在对应的虚函数声明。如果签名不匹配(比如参数类型不同、const 修饰不一致、返回类型协变不满足),编译器会直接报错,而不是静默忽略或意外调用基类版本。
常见错误包括:
void func(int),子类写成 void func(double) —— 这其实是重载,不是重写,override 会让编译器立刻报错virtual void func() const,子类漏写 const —— 签名不一致,没 override 就悄无声息变成新函数Base*,子类返回 Derived* 但没声明为指针/引用)—— override 触发检查它不是修饰符,不能放在返回类型前,也不能用于非虚函数或静态函数。使用时要注意:
const/volatile)、ref-qualifiers(&/&&)完全一致size_t 和 unsigned long 在某些平台不等价)class Base {
public:
virtual void process() const = 0;
virtual std::string name() && = 0;
};
class Derived : public Base {
public:
void process() const override { / OK / } // ✅ 签名完全匹配
std::string name() && override { / OK / } // ✅
void process() override { / ❌ 缺 const,编译失败 / }
void process() const noexcept override { / ❌ 多了 noexcept,不匹配 / }
};
加上 override 不会生成额外代码,也不改变 vtable 布局或调用性能。它的价值纯粹在开发阶段防错:
override 的派生类函数会立即暴露不兼容问题
)应默认启用 -Woverloaded-virtual(Clang/GCC),再配合 override 形成双重保障最容易被忽略的是 ref-qualifier 和异常规范(noexcept)的匹配——它们属于函数类型的一部分,但常被当成“可选修饰”,其实只要不一致,override 就会拒绝编译。