Namespaces
Variants

final specifier (since C++11)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Virtual function
override specifier (C++11)
final specifier (C++11)
Special member functions
Templates
Miscellaneous

派生クラスでの virtual function のオーバーライド、またはクラスの derived from 継承を禁止することを指定します。

目次

翻訳の説明: - 「Contents」を「目次」に翻訳しました - HTMLタグ、属性、
タグ内のテキストは翻訳していません
- C++固有の用語(Syntax、Explanation、Note、Keywords、Example、References、Defect reports、See also)は原文のまま保持しています
- 数値や構造は完全に保持されています

構文

メンバー関数に適用される場合、識別子 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以降)
1) メンバー関数の宣言において、 final は宣言子の直後、 virt-specifier-seq 内に現れることができ、使用される場合は pure-specifier の前に置かれる。
2) メンバ関数定義がクラス定義内にある場合、 final は宣言子の直後、 function-body の直前の virt-specifier-seq 内に記述できます。
3) クラス定義において、 final はクラス名の直後、使用される場合は base-clause が始まるコロンの直前に、 class-virt-specifier として記述できます。
4) クラス定義において、 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 は、メンバー関数の宣言またはクラスヘッドで使用された場合に特別な意味を持つ識別子です。他の文脈では予約されておらず、オブジェクトや関数の命名に使用できます。

注記

以下のトークンのシーケンスにおいて:

  1. class struct union のいずれか
  2. 修飾されている可能性のある 識別子
  3. final
  4. : { のいずれか

シーケンス内の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()
{
}

キーワード

final

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)