跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

C++中的override和final关键字有什么用?(显式覆盖检查与禁止继承)

override用于显式声明覆盖虚函数,防止签名不匹配导致的静默新函数;final用于禁止继承或重写,二者均为编译期检查,零运行时开销。 override 用来告诉编译器“我明确想覆盖基类虚函数” 不加
override
时,哪怕函数签名稍有不同(比如参数类型不一致、const 修饰不匹配、返回类型协变没写对),编译器也不会报错,而是静默地声明了一个**新函数**,而不是覆盖。这会导致运行时调用不到预期的派生类版本,bug 难以发现。 加上
override
后,编译器会严格比对:该函数是否确实存在于某个可访问的基类中、是否为虚函数、签名是否完全匹配(含 const/volatile/ref-qualifier)。不满足任一条件就直接报错。 常见错误现象:
void func(int)
在基类中是
virtual void func(double)
,子类写
void func(int) override
→ 编译失败 使用场景:所有你本意是覆盖虚函数的地方,都应加
override
,尤其是重构后或多人协作时 性能影响:零开销,纯编译期检查 final 用于禁止进一步继承或覆盖
final
可作用于两个位置:类定义后(禁止被继承)、虚函数声明后(禁止被重写)。它不是运行时控制,而是编译期强制约束。 类上加
final
:
class Widget final : public Base { ... };
→ 其他类再继承
Widget
会触发 编译错误 :
error: cannot derive from 'final' class
函数上加
final
:
virtual void draw() final;
→ 派生类中再写
void draw() override
会报错:
error: virtual function 'draw' cannot be overridden
注意:不能同时用
override
和
final
修饰同一个函数——语法允许,但语义上合理(覆盖并封顶),例如:
void draw() override final;
不写 override 的真实风险:签名漂移无人察觉 下面这段代码在没有
override
时能编译通过,但行为不符合直觉: 立即学习 “ C++免费学习笔记(深入) ”; C函数速查手册(CHM版) C函数速查手册(CHM版) 下载
struct Base { virtual void log(const std::string& msg) {} }; struct Derived : Base { void log(std::string msg) { /* 注意:少了 const& */ } }; Base* p = new Derived(); p->log("hello"); // 调用的是 Base::log,不是 Derived::log!
加了
override
后,
Derived::log
那一行立刻报错,问题暴露得早且明确。 容易踩的坑:用 IDE 自动生成重写函数时,有些老版本插件不自动补
override
兼容性:C++11 起支持,所有现代编译器(GCC 4.7+、Clang 3.2+、MSVC 2012+)都完整支持 override 和 final 不解决运行时多态逻辑错误 它们只管“有没有覆盖”和“能不能覆盖”,不管覆盖后的函数逻辑是否正确。比如: 子类
override
了
clone()
,但内部返回了
new Base
而非
new Derived
→ 编译通过,运行时出错 把
final
加在关键算法函数上防止误改,但若该函数本身有逻辑缺陷,
final
反而让修复更麻烦(需改设计) 真正容易被忽略的是:这两个关键字必须配合虚函数机制起作用;非虚函数加
override
是语法错误,加
final
则无意义。

相关文章