名前空間
変種
操作

final 指定子 (C++11 以降)

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
仮想関数
override指定子 (C++11)  
final 指定子 (C++11)
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

派生クラスでオーバーライドできない 仮想関数であることを指定するか、またはクラスから 派生できないことを指定します。

目次

[編集] 構文

メンバ関数に適用される場合、識別子 final は、クラス定義内のメンバ関数宣言またはメンバ関数定義の構文における 宣言子 の直後に現れます。

クラス(struct および union を含む)に適用される場合、識別子 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 は宣言子の直後、pure-specifier(使用されている場合)の前に virt-specifier-seq に現れることがあります。
2) クラス定義内のメンバ関数定義において、final は宣言子の直後、function-body の直前に virt-specifier-seq に現れることがあります。
3) クラス定義において、final はクラス名の直後、base-clause を開始するコロンの直前に class-virt-specifier として現れることがあります(使用されている場合)。
4) クラス定義において、finalclass-prop-specifier-seq に現れることがありますが(使用されている場合)、一度だけです。

ケース (1,2) では、virt-specifier-seq は、使用されている場合、overridefinalfinal override、または override final のいずれかです。ケース (3) では、class-virt-specifier の許可される唯一の値は final です。ケース (4) では、class-prop-specifier-seq は、使用されている場合、任意の数の クラスプロパティ指定子 (C++26 以降) を持つことができますが、それぞれが最大で 1 回しか現れません。

[編集] 説明

仮想関数宣言または定義で使用される場合、final 指定子は、その関数が仮想であることを保証し、派生クラスでオーバーライドできないことを指定します。それ以外の場合は、プログラムは不正な形式になります(コンパイル時エラーが発生します)。

クラス定義で使用される場合、final は、このクラスが別のクラス定義の base-specifier-list に現れることができない(つまり、派生できない)ことを指定します。それ以外の場合は、プログラムは不正な形式になります(コンパイル時エラーが発生します)。finalunion 定義と組み合わせて使用することもできますが、その場合、効果はありません(std::is_final の結果以外) (C++14 以降)。これは、union からは派生できないためです。

final は、メンバ関数宣言またはクラスヘッダーで使用される場合に特別な意味を持つ識別子です。その他のコンテキストでは予約されておらず、オブジェクトや関数の命名に使用できます。

[編集] 注意

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

  1. classstructunion のいずれか
  2. 修飾されている可能性のある 識別子
  3. final
  4. : または { のいずれか

シーケンス内の 3 番目のトークン final は、常に識別子ではなく指定子として解釈されます。

struct A;
struct A final {}; // OK, definition of struct A,
                   // not value-initialization of variable final
 
struct X
{
    struct C { constexpr operator int() { return 5; } };
    struct B final : C{}; // OK, definition of nested class B,
                          // not declaration of a bit-field member final
};
 
// Abnormal final usage.
 
struct final final // OK, definition of a struct named `final` from which
{                  // you cannot inherit
};
 
// struct final final {}; // Error: redefinition of `struct final`, NOT a
                          // definition of a variable `final` using an elaborated
                          // type specifier `struct final` followed by an
                          // aggregate initialization
 
// struct override : final {}; // Error: cannot derive from final base type;
                               // `override` in given context is a normal name
void foo()
{
    [[maybe_unused]]
    final final; // OK, declaration of a variable named `final` of type
                 // `struct final` 
}
 
struct final final; // OK, declaration of a variable named `final` of type
                    // `struct final` using an elaborated type specifier
int main()
{
}

[編集] キーワード

final

[編集]

struct Base
{
    virtual void foo();
};
 
struct A : Base
{
    void foo() final; // Base::foo is overridden and A::foo is the final override
    void bar() final; // Error: bar cannot be final as it is non-virtual
};
 
struct B final : A // struct B is final
{
    void foo() override; // Error: foo cannot be overridden as it is final in A
};
 
struct C : B {}; // Error: B is 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 Classes [class]
  • 11.7.3 Virtual functions [class.virtual]
  • C++20 standard (ISO/IEC 14882:2020)
  • 11 Classes [class]
  • 11.7.2 Virtual functions [class.virtual]
  • C++17 standard (ISO/IEC 14882:2017)
  • 12 Classes [class]
  • 13.3 Virtual functions [class.virtual]
  • C++14 standard (ISO/IEC 14882:2014)
  • 9 Classes [class]
  • 10.3 Virtual functions [class.virtual]
  • C++11 standard (ISO/IEC 14882:2011)
  • 9 Classes [class]
  • 10.3 Virtual functions [class.virtual]

[編集] 不具合報告

以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。

DR 適用対象 公開された動作 正しい動作
CWG 1318 C++11 クラス名と
空のメンバ仕様リストの後に final を持つクラス定義は、final を識別子と見なす可能性があります。
final は常に
この場合、指定子です。

[編集] 関連項目

override 指定子 (C++11) メソッドが別のメソッドをオーバーライドすることを明示的に宣言します[編集]
クラスプロパティ指定子 (C++26) final 指定子 (C++11)置換可能性 (C++26)自明な移動可能性 (C++26)[編集]
English 日本語 中文(简体) 中文(繁體)