final
specifier
(since C++11)
派生クラスでの virtual function のオーバーライド、またはクラスの derived from 継承を禁止することを指定します。
目次 |
、
、
構文
メンバー関数に適用される場合、識別子
final
は、
declarator
の直後、クラス定義内のメンバー関数宣言またはメンバー関数定義の構文に現れます。
クラス(構造体および共用体を含む)に適用される場合、識別子
final
はクラス定義の先頭、クラス名の直後に記述され、クラス宣言内に現れることはできません。
| declarator virt-specifier-seq (オプション) pure-specifier (オプション) | (1) | ||||||||
| declarator virt-specifier-seq (オプション) function-body | (2) | ||||||||
| class-key attr (オプション) class-head-name class-virt-specifier (オプション) base-clause (オプション) | (3) | (C++26まで) | |||||||
| class-key attr (オプション) class-head-name class-prop-specifier-seq (オプション) base-clause (オプション) | (4) | (C++26以降) | |||||||
final
は宣言子の直後、
function-body
の直前の
virt-specifier-seq
内に記述できます。
final
はクラス名の直後、使用される場合は
base-clause
が始まるコロンの直前に、
class-virt-specifier
として記述できます。
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以降)
を持つことができますが、各指定子は最大1回しか現れません。
説明
仮想関数の宣言または定義で使用される場合、 final 指定子は、その関数が仮想関数であることを保証し、派生クラスでオーバーライドできないことを指定します。それ以外の場合、プログラムは不適格となります(コンパイル時エラーが生成されます)。
クラス定義で使用される場合、 final は、このクラスが他のクラス定義の base-specifier-list に現れてはならないことを指定します(つまり、派生クラスを作成できません)。それ以外の場合、プログラムは不適格となります(コンパイル時エラーが発生します)。 final は union 定義でも使用できますが、この場合 ( std::is_final の結果に影響を与えること以外は) (C++14以降) 効果はありません。なぜならunionは派生できないからです。
final は、メンバー関数の宣言またはクラスヘッドで使用された場合に特別な意味を持つ識別子です。他の文脈では予約されておらず、オブジェクトや関数の命名に使用できます。
注記
以下のトークンのシーケンスにおいて:
- class 、 struct 、 union のいずれか
- 修飾されている可能性のある 識別子
- final
- : と { のいずれか
シーケンス内の3番目のトークン final は、常に識別子ではなく指定子として扱われます。
struct A; struct A final {}; // OK: 構造体Aの定義、 // 変数finalの値初期化ではない struct X { struct C { constexpr operator int() { return 5; } }; struct B final : C{}; // OK: ネストされたクラスBの定義、 // ビットフィールドメンバーfinalの宣言ではない }; // 異常なfinalの使用法 struct final final // OK: `final`という名前の構造体の定義(この構造体からは { // 継承できない) }; // struct final final {}; // エラー: `struct final`の再定義、 // 詳細型指定子`struct final`に続く集成体初期化による // 変数`final`の定義ではない // struct override : final {}; // エラー: final基底型から派生できない; // この文脈における`override`は通常の名前 void foo() { [[maybe_unused]] final final; // OK: 型`struct final`の`final`という名前の変数の宣言 // } struct final final; // OK: 詳細型指定子を使用した型`struct final`の // `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++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 1318 | C++11 |
クラス名の後に
final
があり、空のメンバー指定リストを持つクラス定義では
final が識別子として扱われる可能性があった |
final
はこの場合常に
指定子として扱われる |
関連項目
override
指定子
(C++11)
|
メソッドが他のメソッドをオーバーライドすることを明示的に宣言する |
| クラスプロパティ指定子 (C++26) | final 指定子 (C++11) , 置換可能性 (C++26) , 自明な再配置可能性 (C++26) |