指定某个虚函数不能在子类中被覆盖,或者某个类不能被子类继承

语法

当应用到成员函数时,标识符 final 在类定义中的成员函数声明或成员函数定义的语法中,紧随声明符之后出现。

当应用到类时,标识符 final 出现在类定义的开头,紧跟类名之后出现。

声明符 虚说明符序列(可选) 纯说明符(可选) (1)
声明符 虚说明符序列(可选) 函数体 (2)
类关键词 attr(可选) 类头名 类虚说明符(可选) 基类子句(可选) (3)

1) 在成员函数声明中,final 可在紧跟声明符之后的 虚说明符序列 中出现,而若使用 纯说明符 则在其之前。

2) 在类定义内的成员函数定义中,final 可在紧跟声明符之后并紧接 函数体 之前的 虚说明符序列 中出现。

3) 在类定义中,final 可在紧跟类名之后,紧接 基类子句(若使用它)起头的冒号之前,作为 类虚说明符 出现。

情况 (1,2) 中,若使用 虚说明符序列,则它是 overridefinalfinal overrideoverride final 之一。情况 (3) 中,若使用 类虚说明符 则仅允许 final

解释

当在虚函数声明或定义中使用时,final 确保函数为虚并指定其不可被派生类覆盖。若这么做则程序非良构(生成编译时错误)。

当在类定义中使用时,final 指定此类不可在另一类的定义中的 基类说明符列表 中出现(换言之,不能派生于它)。若这么做则程序非良构(生成编译时错误)。final 亦可用于联合体定义,此情况下它没有效果(除了 std::is_final 的输出结果),因为不能从联合体派生。

final 是在成员函数声明或类头部中使用时有特殊含义的标识符。其他语境中它未被保留,而且可用于命名对象或函数。

示例

运行此代码

  1. struct Base
  2. {
  3. virtual void foo();
  4. };
  5.  
  6. struct A : Base
  7. {
  8. void foo() final; // Base::foo 被覆盖而 A::foo 是最终覆盖函数
  9. void bar() final; // 错误: bar 不能为 final 因为它非虚
  10. };
  11.  
  12. struct B final : A // struct B 为 final
  13. {
  14. void foo() override; // 错误:foo 不能被覆盖,因为它在 A 中是 final
  15. };
  16.  
  17. struct C : B // 错误:B 为 final
  18. {
  19. };