final只能加在类名后或虚函数声明末尾,且位置严格:类名后紧贴、花括号前;虚函数需在参数列表及限定符后、分号或函数体前;非虚函数加final报错;private构造等替代方案无效且干扰优化。

直接在类名后加 final,或在虚函数声明末尾加 final,是唯一编译器强制生效、无运行时开销的写法。其他任何位置或组合都无效或报错。
class 后紧贴写 final 才禁止继承
语法位置极其敏感:必须紧跟类名、位于花括号 { 之前,中间不能换行、不能有空格或继承列表隔开。
-
class Widget final { };✅ 正确 -
class final Widget { };❌ 编译器当普通标识符,不报错但完全无效 -
class Widget { } final;❌ 语法错误,final不是语句后缀 -
class Derived : public MathUtils final { };❌ 错误写法;正确应是基类MathUtils自身声明为final,派生类写法不变但编译会立即报error: cannot derive from 'final' base class 'MathUtils'
只能修饰虚函数,final 放在参数列表之后
final 对非虚函数无效,编译器会直接报错。它只作用于已有虚函数(包括从基类继承来的),且必须出现在函数声明末尾,即右括号 ) 和 const/override 等限定符之后、函数体或分号之前。
-
virtual void step() final { }✅ 类内定义 -
virtual void execute() const final;✅ 声明中带const,final在最后 -
virtual void run() final = 0;✅ 纯虚函数,final在= 0前 -
void func() final { }❌ 非虚函数,编译失败 -
virtual void f() final override;✅ 合法,override和final可共存
别用 private 构造函数等“软限制”替代 final
靠访问控制模拟禁止继承,既不可靠又干扰优化:
- 私有构造函数 + 友元类 →
class B : public A { };仍能编译通过,只是B b;失败 - protected 析构函数 → 只阻止栈上实例化,不影响继承声明本身
-
static_assert(!std::is_base_of_v<base t>)→ 仅在模板实例化时触发,对普通继承完全无感 - 这些方式还可能破坏内联、增加虚表大小、让 IDE 跳转失效
真正该加 final 的地方,是你写完类就该决定的:这个类是否允许别人改写它的类型关系?答案是否,就立刻加。不是所有“看起来像禁止”的做法都算数,只有语法层的 final 是编译器真正在意的锁。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











