final用于类后禁止继承,用于虚函数后禁止重写;仅适用于类定义和虚函数声明,不可用于普通函数、变量或命名空间,且无传递性。

final 用在类定义后禁止继承
在 C++11 及以后,final 是一个标识符(不是关键字,但有保留语义),加在类名后面能明确阻止其他类从它派生。一旦标记为 final,任何尝试继承它的行为都会触发编译错误。
常见错误现象:error: cannot derive from 'final' base class 或类似提示,通常出现在子类声明时。
- 写法必须紧贴类名后、花括号前:
class Base final { ... }; - 不能写成
class final Base { ... };—— 这是语法错误 - 模板类也能用:
templateclass Container final { ... }; - 注意:
final不影响友元、成员访问控制,只约束继承关系
final 用在虚函数声明后禁止重写
当某个虚函数不希望被派生类覆盖时,在其声明末尾加 final,就能让编译器在子类中尝试重写该函数时报错。
使用场景:基类已提供最稳定实现(如关键协议方法、安全校验逻辑),业务层不得修改行为。
立即学习“C++免费学习笔记(深入)”;
- 只能用于虚函数(包括纯虚函数),非虚函数加
final是非法的 - 写法示例:
virtual void process() final;或virtual int get_id() const final = 0; - 若子类中声明同签名函数,即使没加
override,也会报错:error: virtual function 'process' cannot be overridden because it is final -
final和override可同时出现,但顺序必须是virtual void f() override final;
final 不能用在普通函数、变量或命名空间里
final 的作用域非常受限,仅对类和虚函数有效。试图在其他位置使用会导致编译失败。
容易踩的坑:
- 写成
void func() final {}—— 编译器报error: 'final' cannot be used here - 在变量声明前加
final int x = 42;—— 这不是 C++ 的语法,C++ 中没有“变量 final”概念(那是 Java/C# 的用法) - 在命名空间或函数体内写
final—— 无意义,直接报错 - 误以为
final能阻止对象复制或移动 —— 它完全不干预构造、析构、赋值等操作
和 sealed / override 的兼容性与注意事项
C++ 标准只认 final 和 override,没有 sealed(那是 C++/CLI 或 C# 的)。有些旧代码或跨平台项目可能混用宏封装,需特别注意展开后是否符合标准语法。
性能影响几乎为零:这些是编译期约束,不生成额外运行时代码,也不影响内联或虚表布局(除非编译器据此做优化)。
- 基类函数标了
final,派生类仍可定义同名非虚函数(隐藏而非重写),但这通常违背设计意图,建议配合override使用以避免意外隐藏 - 多重继承中,只要任一基类的虚函数被标为
final,所有路径上都不允许重写它 - 头文件中使用
final时,确保所有依赖方都支持 C++11 或更高标准(g++ -std=c++11,MSVC 2012+)
真正容易被忽略的是:final 不具备传递性 —— 父类标记 final 只锁住直接继承,不影响其成员函数是否可被间接调用;而函数级 final 只封死那一个签名,不阻止重载其他参数版本。这两点在大型继承体系中经常引发理解偏差。











