Declarations
宣言 は、名前をC++プログラムに導入(または再導入)する方法です。すべての宣言が実際に何かを宣言するわけではなく、各種エンティティはそれぞれ異なる方法で宣言されます。 定義 は、名前で識別されるエンティティを使用するのに十分な宣言です。
宣言は以下のいずれかです:
|
(C++11以降) |
-
空の宣言 (
;) - decl-specifier-seq を持たない関数宣言:
attr
(任意)
declarator
;
|
|||||||||
| attr | - | (since C++11) 任意の数の 属性 のシーケンス |
| declarator | - | 関数宣言子 |
- この宣言はコンストラクタ、デストラクタ、またはユーザー定義型の conversion function を宣言しなければなりません。これは template declaration 、 explicit specialization または明示的インスタンス化の一部としてのみ使用できます。
- block-declaration (ブロック内に現れることができる宣言( ブロック を参照))。これは以下のいずれかになります:
| (C++11以降) |
| (C++20以降) | |
| (C++11以降) |
-
- 単純宣言
目次 |
単純宣言
単純宣言は、1つまたは複数の識別子(通常は変数)を導入し、作成し、必要に応じて初期化する文です。
decl-specifier-seq
init-declarator-list
(省略可能)
;
|
(1) | ||||||||
attr
decl-specifier-seq
init-declarator-list
;
|
(2) | (C++11以降) | |||||||
| decl-specifier-seq | - | 一連の 指定子 |
| init-declarator-list | - | init-declarator のカンマ区切りリスト(下記参照) |
| attr | - | 任意の数の 属性 のシーケンス |
init-declarator-list
は、名前付きクラスまたは名前付き列挙型を宣言する場合にのみ省略できます。
|
構造化束縛宣言 も単純宣言である。 |
(C++17以降) |
init-declarator
の構文は以下のように定義されます:
| declarator initializer | (1) | ||||||||
| declarator requires-clause (オプション) contract-specs (オプション) | (2) | ||||||||
| declarator | - | a declarator |
| initializer | - | an initializer |
| requires-clause | - | (since C++20) a requires clause |
| contract-specs | - | (since C++26) a list of function contract specifiers |
|
requires-clause は、 declarator が テンプレート化された関数 を宣言する場合にのみ現れます。 |
(C++20以降) |
|
contract-specs は、 declarator が関数または関数テンプレートを宣言する場合にのみ現れます。 |
(C++26以降) |
指定子
宣言指定子 ( decl-specifier-seq ) は、任意の順序で以下の空白区切りの指定子の列です:
-
the
typedef指定子。存在する場合、宣言全体は typedef宣言 となり、各宣言子はオブジェクトや関数ではなく新しい型名を導入します。 -
関数指定子 (
inline,virtual,explicit)、 関数宣言 でのみ許可されます。
|
(C++17以降) |
-
the
friend指定子、クラスおよび関数宣言で許可されます。
|
(C++11以降) |
| (C++20以降) |
- ストレージクラス指定子 ( register , (C++17まで) static , thread_local , (C++11から) extern , mutable )。ストレージクラス指定子は1つだけ許可される 、ただし thread_local は extern または static と一緒に使用できる (C++11から) 。
- 型指定子 ( type-specifier-seq )、型を指定する一連の指定子。宣言によって導入されるすべてのエンティティの型は、この型(必要に応じて宣言子によって修飾される)となる。この一連の指定子は type-id でも使用される。 type-specifier-seq の一部となる指定子は以下のみ(任意の順序で):
| (C++11以降) | |
| (C++26以降) |
-
-
- 以前に宣言されたクラス名(オプションで 修飾 可能)
- 以前に宣言されたenum名(オプションで 修飾 可能)
- 以前に宣言された typedef-name または type alias (C++11以降) (オプションで 修飾 可能)
- テンプレート引数を伴うテンプレート名(オプションで 修飾 可能、オプションで template disambiguator を使用可能)
-
|
(C++17以降) |
-
-
decl-specifier-seqでは、以下の例外を除いて型指定子は1つだけ許可されます:
- const は自身を除く任意の型指定子と組み合わせ可能。
- volatile は自身を除く任意の型指定子と組み合わせ可能。
- signed または unsigned は char 、 long 、 short 、または int と組み合わせ可能。
- short または long は int と組み合わせ可能。
- long は double と組み合わせ可能。
|
(C++11以降) |
Attributes は decl-specifier-seq 内に現れることがあり、その場合、それらは先行する指定子によって決定される型に適用されます。
宣言指定子シーケンス内での任意の指定子の繰り返し、例えば decl-specifier-seq 内の const static const や virtual inline virtual はエラーとなります 、ただし long が2回出現することは許可されます (C++11以降) 。
宣言子
init-declarator-list 内の各 init-declarator は、同じ指定子を持つ独立した宣言であるかのように処理されます: S D1, D2, D3 ; は S D1 ; S D2 ; S D3 ; として扱われます。
各宣言子は、正確に1つのオブジェクト、参照、関数、または(typedef宣言の場合)型エイリアスを導入します。その型は decl-specifier-seq によって提供され、宣言子内の & (参照)や [ ] (配列)や ( ) (関数返却)などの演算子によって任意に修飾されます。これらの演算子は、以下に示すように再帰的に適用できます。
A 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
[
constant-expression
(任意)
]
attr
(任意)
|
(8) | ||||||||
noptr-declarator
(
parameter-list
)
cv
(任意)
ref
(任意)
except
(任意)
attr
(任意)
|
(9) | ||||||||
(
declarator
)
|
(10) | ||||||||
D
を
C
のメンバへのポインタとして宣言し、その型は
decl-specifier-seq
S
によって決定される。
nested-name-specifier
は
名前とスコープ解決演算子のシーケンス
::
|
すべての場合において、 attr はオプションの 属性 シーケンスです。識別子の直後に現れる場合、宣言されるオブジェクトに適用されます。 |
(C++11以降) |
cv は const および volatile 修飾子のシーケンスであり、各修飾子はシーケンス内に最大1回のみ出現することができます。
|
この節は不完全です
理由: 宣言名の隠蔽ルールを説明する必要があります。変数/関数の宣言が同じ名前のクラス(ただしtypedefは除く)をどのように隠蔽するか |
注記
ブロック内で block-declaration が現れた場合、かつ宣言によって導入された識別子が以前に外側のブロックで宣言されていたとき、 外側の宣言は隠蔽されます (そのブロックの残りの部分に対して)。
自動記憶域期間を持つ変数を宣言する場合、その宣言文が実行されるときに初期化されます。ブロック内で宣言されたすべての自動変数は、ブロックから退出する際に(例外、goto、またはブロック終端への到達など、どのようにブロックを退出したかに関係なく)破棄され、初期化の順序と逆の順序で破棄されます。
例
注: この例は、複雑な宣言が言語文法の観点からどのように解析されるかを示しています。他の一般的な記憶法としては: スパイラルルール 、 内側から外側への読み方 、および 宣言が使用法を反映する があります。また自動解析ツールが https://cdecl.org で利用可能です。
#include <type_traits> struct S { int member; // decl-specifier-seq is "int" // declarator is "member" } obj, *pObj(&obj); // decl-specifier-seq is "struct S { int member; }" // declarator "obj" declares an object of type S // declarator "*pObj" declares a pointer to S, // and initializer "(&obj)" initializes it int i = 1, *p = nullptr, f(), (*pf)(double); // decl-specifier-seq is "int" // declarator "i" declares a variable of type int, // and initializer "= 1" initializes it // declarator "*p" declares a variable of type int*, // and initializer "= nullptr" initializes it // declarator "f()" declares (but doesn't define) // a function taking no arguments and returning int // declarator "(*pf)(double)" declares a pointer to function // taking double and returning int int (*(*var1)(double))[3] = nullptr; // decl-specifier-seq is "int" // declarator is "(*(*var1)(double))[3]" // initializer is "= nullptr" // 1. declarator "(*(*var1)(double))[3]" is an array declarator: // Type declared is: "(*(*var1)(double))" array of 3 elements // 2. declarator "(*(*var1)(double))" is a pointer declarator: // Type declared is: "(*var1)(double)" pointer to array of 3 elements // 3. declarator "(*var1)(double)" is a function declarator: // Type declared is: "(*var1)" function taking "(double)", // returning pointer to array of 3 elements. // 4. declarator "(*var1)" is a pointer declarator: // Type declared is: "var1" pointer to function taking "(double)", // returning pointer to array of 3 elements. // 5. declarator "var1" is an identifier. // This declaration declares the object var1 of type "pointer to function // taking double and returning pointer to array of 3 elements of type int" // The initializer "= nullptr" provides the initial value of this pointer. // C++11 alternative syntax: auto (*var2)(double) -> int (*)[3] = nullptr; // decl-specifier-seq is "auto" // declarator is "(*var2)(double) -> int (*)[3]" // initializer is "= nullptr" // 1. declarator "(*var2)(double) -> int (*)[3]" is a function declarator: // Type declared is: "(*var2)" function taking "(double)", returning "int (*)[3]" // ... int main() { static_assert(std::is_same_v<decltype(var1), decltype(var2)>); }
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用バージョン | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 482 | C++98 | 再宣言の宣言子は修飾できなかった | 修飾された宣言子が許可される |
| CWG 569 | C++98 | 単独のセミコロンは有効な宣言ではなかった |
空宣言となり、
効果を持たない |
| CWG 1830 | C++98 | decl-specifier-seq 内での関数指定子の繰り返しが許可されていた | 繰り返しは禁止される |
関連項目
|
C ドキュメント
for
宣言
|