final
specifier
(since C++11)
指定一个 虚函数 不能在派生类中被重写,或者某个类不能被 继承 。
目录 |
语法
当应用于成员函数时,标识符
final
在类定义中的成员函数声明或成员函数定义语法里,紧跟在
声明符
之后出现。
当应用于类(包括结构体和联合体)时,标识符
final
出现在类定义的开头,紧跟在类名之后,且不能在类声明中出现。
| 声明符 虚说明符序列 (可选) 纯说明符 (可选) | (1) | ||||||||
| 声明符 虚说明符序列 (可选) 函数体 | (2) | ||||||||
| 类关键字 属性 (可选) 类头名称 类虚说明符 (可选) 基类子句 (可选) | (3) | (C++26 前) | |||||||
| 类关键字 属性 (可选) 类头名称 类属性说明符序列 (可选) 基类子句 (可选) | (4) | (C++26 起) | |||||||
final
可以出现在声明符之后、
函数体
之前的
虚说明符序列
中。
final
可作为
class-virt-specifier
紧跟在类名之后出现,恰好在开始
base-clause
的冒号之前(如果使用的话)。
final
可以出现在
class-prop-specifier-seq
中,如果使用,则只能出现一次。
在情况
(1,2)
中,
virt-specifier-seq
(若使用)可以是
override
或
final
,或
final override
或
override final
。在情况
(3)
中,
class-virt-specifier
(若使用)唯一允许的值为
final
。在情况
(4)
中,
class-prop-specifier-seq
(若使用)可包含任意数量的
类属性说明符
(自 C++26 起)
,但每个说明符最多只能出现一次。
说明
当在虚函数声明或定义中使用时, final 说明符确保该函数为虚函数,并规定其不能被派生类重写。否则程序将是非良构的(会产生编译时错误)。
在类定义中使用时, final 指定该类不能出现在其他类定义的 基类说明符列表 中(即不能被继承)。否则程序非良构(将产生编译时错误)。 final 也可用于 联合体 定义,此时该限定符没有实际作用 (仅影响 std::is_final 的判定结果) (C++14 起) ,因为联合体本身不能被继承。
final 是一个在成员函数声明或类头部使用时具有特殊含义的标识符。在其他上下文中,它不被保留,可用于命名对象和函数。
注意
在以下标记序列中:
- class 、 struct 和 union 其中之一
- 可能带有限定符的 标识符
- final
- : 或 { 其中之一
序列中的第三个标记 final 始终被视为说明符而非标识符。
struct A; struct A final {}; // 正确:结构体 A 的定义, // 不是变量 final 的值初始化 struct X { struct C { constexpr operator int() { return 5; } }; struct B final : C{}; // 正确:嵌套类 B 的定义, // 不是位域成员 final 的声明 }; // 异常的 final 用法 struct final final // 正确:定义了一个名为 `final` 的结构体, { // 无法从其继承 }; // struct final final {}; // 错误:`struct final` 重定义,不是 // 使用详细类型说明符 `struct final` 后接聚合初始化 // 来定义变量 `final` // struct override : final {}; // 错误:无法从 final 基类派生; // 在此上下文中 `override` 是普通名称 void foo() { [[maybe_unused]] final final; // 正确:声明一个名为 `final` 的变量,类型为 // `struct final` } struct final final; // 正确:使用详细类型说明符声明一个名为 `final` 的变量, // 类型为 `struct final` int main() { }
关键词
示例
struct Base { virtual void foo(); }; struct A : Base { void foo() final; // Base::foo 被重写,A::foo 成为最终重写版本 void bar() final; // 错误:bar 不能声明为 final,因为它非虚函数 }; struct B final : A // struct B 被声明为 final { void foo() override; // 错误:foo 不可重写,因为它在 A 中已声明为 final }; struct C : B {}; // 错误:B 是 final 类型
可能的输出:
main.cpp:9:10: error: 'void A::bar()' marked 'final', but is not virtual
9 | void bar() final; // Error: bar cannot be final as it is non-virtual
| ^~~
main.cpp:14:10: error: virtual function 'virtual void B::foo()' overriding final function
14 | void foo() override; // Error: foo cannot be overridden as it is final in A
| ^~~
main.cpp:8:10: note: overridden function is 'virtual void A::foo()'
8 | void foo() final; // Base::foo is overridden and A::foo is the final override
| ^~~
main.cpp:17:8: error: cannot derive from 'final' base 'B' in derived type 'C'
17 | struct C : B // Error: B is final
|
参考文献
- C++23 标准 (ISO/IEC 14882:2024):
-
- 11 类 [class]
-
- 11.7.3 虚函数 [class.virtual]
- C++20 标准 (ISO/IEC 14882:2020):
-
- 11 类 [class]
-
- 11.7.2 虚函数 [class.virtual]
- C++17 标准 (ISO/IEC 14882:2017):
-
- 12 类 [class]
-
- 13.3 虚函数 [class.virtual]
- C++14 标准 (ISO/IEC 14882:2014):
-
- 9 类 [class]
-
- 10.3 虚函数 [class.virtual]
- C++11 标准 (ISO/IEC 14882:2011):
-
- 9 类 [class]
-
- 10.3 虚函数 [class.virtual]
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 应用于 | 发布时的行为 | 正确行为 |
|---|---|---|---|
| CWG 1318 | C++11 |
在类名后使用
final
且成员声明列表为空时,
可能使 final 被识别为标识符 |
final
在此情况下始终是
说明符 |
参见
override
说明符
(C++11)
|
显式声明方法重写另一个方法 |
| 类属性说明符 (C++26) | final 说明符 (C++11) , 可替换性 (C++26) , 平凡可重定位性 (C++26) |