名前空間
変種
操作

宣言

提供: cppreference.com
< cpp‎ | language
 
 
 
 

宣言は名前を C++ プログラムに導入 (または再導入) します。 エンティティの種類ごとに宣言は異なります。 定義はその名前によって識別されるエンティティを使用するのに十分な宣言です。

宣言は以下のいずれかです。

attr(オプション) declarator ;
attr (C++11およびそれ以降) - 任意の数の属性の並び
declarator - 関数宣言子
この宣言はコンストラクタ、デストラクタ、またはユーザ定義型の変換関数の宣言でなければなりません。 これはテンプレート宣言明示的特殊化または明示的実体化の一部としてのみ使用できます。
  • ブロック宣言 (ブロック内部で現れることができる宣言)。 これは以下のいずれかです。

目次

[編集] 単純宣言

単純宣言は、ひとつまたはいくつかの識別子 (一般的には変数) を導入、作成、およびオプショナルに初期化する文です。

decl-specifier-seq init-declarator-list(オプション) ; (1)
attr decl-specifier-seq init-declarator-list; (2)
attr (C++11およびそれ以降) - 任意の数の属性の並び
decl-specifier-seq - 指定子の並び (後述)
init-declarator-list - オプショナルな初期化子付きの宣言子のコンマ区切りのリスト。 名前付きのクラス、構造体、共用体または名前付きの列挙を宣言するとき、 init-declarator-list はオプショナルです

構造化束縛宣言も単純宣言です。 (C++17およびそれ以降)

[編集] 指定子

宣言指定子 (decl-specifier-seq) は以下の指定子のホワイトスペースで区切られた並びです (順不同)。

  • inline 指定子は変数宣言でも使用できます。
(C++17およびそれ以降)
  • friend 指定子。 クラスおよび関数宣言でのみ使用できます。
  • constexpr 指定子。 変数定義、関数および関数テンプレート宣言、およびリテラル型の静的データメンバの宣言でのみ使用できます。
  • 記憶域クラス指定子 (register, static, thread_local (C++11およびそれ以降), extern, mutable)。 ひとつの記憶域クラス指定子のみ指定できます。 ただし thread_localextern または static と一緒に使用できます。
  • 型指定子 (type-specifier-seq)。 型を表す指定子の並び。 宣言によって導入されるすべてのエンティティの型はこの型であり、オプションで宣言子 (下記参照) によって変更できます。 この一連の指定子は type-id によっても使用されます。 以下の指定子のみが type-specifier-seq の一部になれます (順不同)。
(C++11およびそれ以降)
(C++17およびそれ以降)
  • キーワード classstruct または union に、以前に定義されたクラス、構造体または共用体の識別子が続いたもの (修飾付きでも構いません)
  • キーワード classstruct または union に、以前にクラステンプレートの名前として定義された、テンプレート引数付きのテンプレート名が続いたもの (修飾付きでも構いません) (テンプレート曖昧性解消子を用いても構いません)
  • キーワード enum に、以前に列挙の名前として宣言された識別子が続いたもの (修飾付きでも構いません)
decl-specifier-seq 内でひとつだけ型指定子を指定できます。 ただし以下の例外があります。
- const はそれ自身を除く任意の型指定子と組み合わせることができます。
- volatile はそれ自身を除く任意の型指定子と組み合わせることができます。
- signed, unsignedchar, long, short または int と組み合わせることができます。
- short, longint と組み合わせることができます。
- longdouble と組み合わせることができます。
- longlong と組み合わせることができます。
(C++11およびそれ以降)

属性decl-specifier-seq 内に現れることができます。 この場合、それらは先行する指定子によって決定される型に適用されます。

decl-specifier-seq に2回現れることが許される指定子は long だけです (連続して2回現れることができます)。 他のすべての指定子の繰り返し (const static constvirtual inline virtual など) はエラーです。

(C++17およびそれ以降)

[編集] 宣言子

init-declarator-list は1つ以上の init-declarators のコンマ区切りの並びです。 init-declarators は以下の構文を持ちます。

declarator initializer(オプション) (1)
declarator requires-clause (2) (C++20およびそれ以降)
declarator - 宣言子
initializer - オプショナルな初期化子 (ただし、参照や const オブジェクトを初期化するときなどは必須です)。 詳細は初期化を参照してください
requires-clause(C++20) - requires 節関数宣言制約を追加します

init-declaractor の並び S D1, D2, D3; におけるそれぞれの init-declaractor は、同じ指定子を持つ独立した宣言 S D1; S D2; S D3; であるかのように処理されます。

それぞれの宣言子はちょうどひとつのオブジェクト、参照、関数、または (typedef 宣言の場合は) 型エイリアスを導入します。 その型は decl-specifier-seq によって提供され、オプションで宣言子内の & (参照) または [] (配列) または () (関数の戻り) などの演算子によって変更されます。 これらの演算子は、下に示すように、再帰的に適用できます。

declarator は以下のいずれかです。

unqualified-id attr(オプション) (1)
qualified-id attr(オプション) (2)
... identifier attr(オプション) (3) (C++11およびそれ以降)
* attr(オプション) cv(オプション) declarator (4)
nested-name-specifier * attr(オプション) cv(オプション) declarator (5)
& attr(オプション) declarator (6)
&& attr(オプション) declarator (7) (C++11およびそれ以降)
noptr-declarator [ constexpr(オプション) ] attr(オプション) (8)
noptr-declarator ( parameter-list ) cv(オプション) ref(オプション) except(オプション) attr(オプション) (9)
1) 宣言される name
2) 修飾付き識別子 (qualified-id) を使用する宣言子は、以前に宣言された名前空間メンバまたは クラスメンバを定義または再宣言します。
3) パラメータパック引数宣言でのみ使用できます。
4) ポインタ宣言子。 宣言 S * D;decl-specifier-seq S によって決定される型へのポインタとして D を宣言します。
5) メンバポインタ宣言。 宣言 S C::* D;decl-specifier-seq S によって決定される型の C のメンバへのポインタとして D を宣言します。 nested-name-specifier名前とスコープ解決演算子 :: の並びです。
6) 左辺値参照宣言子。 宣言 S & D;decl-specifier-seq S によって決定される型への左辺値参照として D を宣言します。
7) 右辺値参照宣言子。 宣言 S && D;decl-specifier-seq S によって決定される型への右辺値参照として D を宣言します。
8) 配列宣言子noptr-declarator は任意の有効な宣言子です。 ただし *&&& で始まる場合は括弧で囲む必要があります。
9) 関数宣言子noptr-declarator は任意の有効な宣言子です。 ただし *&&& で始まる場合は括弧で囲む必要があります。 最も外側の関数宣言子はオプショナルな後置戻り値型で終わっても構わないことに注意してください。

すべての場合において、 attr はオプショナルな属性の並びです。 識別子の直後に現れたときは、宣言されているオブジェクトに適用されます。

cvconst および volatile 修飾子の並びです。 ただしそれぞれの修飾子は並びの中に多くとも1度だけ現れることができます。

[編集] ノート

ブロック宣言がブロックの内部に現れ、宣言によって導入された識別子が外側のブロックで以前に宣言されていた場合、そのブロックの残りに対して外側の宣言は隠蔽されます

宣言が自動記憶域期間を持つ変数を導入する場合、それはその宣言文が実行されたときに初期化されます。 ブロック内で宣言されたすべての自動変数は、そのブロックから抜けるとき (例外goto、または終端に達したなど、どのように抜けるかにかかわらず)、それらの初期化の順序の逆順で、破棄されます。

[編集]

#include <string>
 
class C {
    std::string member; // 宣言指定子は「std::string」です。
                        // 宣言子は「member」です。
} obj, *pObj(&obj);
// 宣言指定子は「class C { std::string member; }」です。
// 宣言子「obj」は C 型のオブジェクトを定義します。
// 宣言子「*pObj(&obj)」は C へのポインタを宣言および初期化します。
 
int a = 1, *p = nullptr, f(), (*pf)(double);
// 宣言指定子は int です。
// 宣言子 a = 1 は int 型の変数を定義および初期化します。
// 宣言子 *p = nullptr は int* 型の変数を定義および初期化します。
// 宣言子 (f)() は int を返し引数を取らない関数を宣言します (が定義はしません)。
// 宣言子 (*pf)(double) は int を返し double を取る関数へのポインタを定義します。
 
int (*(*foo)(double))[3] = nullptr;
// 宣言指定子は int です。
// 1. 宣言子「(*(*foo)(double))[3]」は配列宣言子です。
//    宣言された内容は「int 3個の配列 *(*foo)(double)」です。
// 2. 宣言子「*(*foo)(double)」はポインタ宣言子です。
//    宣言された内容は「int 3個の配列へのポインタ (*foo)(double)」です。
// 3. 宣言子「(*foo)(double)」は関数宣言子です。
//    宣言された内容は「int 3個の配列へのポインタを返し double を取る関数 *foo」です。
// 4. 宣言子「*foo」はポインタ宣言子です。
//    宣言された内容は「int 3個の配列へのポインタを返し double を取る関数へのポインタ foo」です。
// 5. 宣言子「foo」は識別子です。
// この宣言は「int 3個の配列へのポインタを返し double を取る関数へのポインタ」型のオブジェクト foo を宣言します。
// 初期化子「= nullptr」はこのポインタの初期値を提供します。