Class declaration
クラスはユーザー定義型であり、クラス指定子によって定義されます。クラス指定子は decl-specifier-seq 内に現れ、これは 宣言 構文の一部です。
目次 |
構文
クラス指定子は以下の構文を持ちます:
class-key
attr
(任意)
class-head-name
class-property-specs
(任意)
base-clause
(任意)
{
member-specification
}
|
(1) | ||||||||
class-key
attr
(任意)
base-clause
(任意)
{
member-specification
}
|
(2) | ||||||||
| class-key | - | class 、 struct 、 union のいずれか。 class と struct は、デフォルトの メンバーアクセス とデフォルトの 基底クラスアクセス を除いて同一です。 union の場合、この宣言は 共用体型 を導入します。 | ||||||||
| attr | - |
(C++11以降)
任意の数の
属性
、
alignas
指定子を含む場合があります
|
||||||||
| class-head-name | - | 定義されるクラスの名前(オプションで 修飾 可能) | ||||||||
| class-property-specs | - |
以下の指定子のリスト。各指定子は各シーケンスで最大1回使用可能です。
|
||||||||
| base-clause | - | 1つ以上の基底クラスと各クラスで使用される継承モデルのリスト( 派生クラス を参照) | ||||||||
| member-specification | - | アクセス指定子、メンバーオブジェクトおよびメンバー関数の宣言と定義のリスト( 後述参照 ) |
前方宣言
以下の形式の宣言
class-key
attr
identifier
;
|
|||||||||
このスコープ内で後ほど定義されるクラス型を宣言します。定義が現れるまで、このクラス名は incomplete type を持ちます。これにより相互参照するクラスが可能になります:
class Vector; // 前方宣言 class Matrix { // ... friend Vector operator*(const Matrix&, const Vector&); }; class Vector { // ... friend Vector operator*(const Matrix&, const Vector&); };
また、特定のソースファイルがクラスへのポインタと参照のみを使用する場合、これにより #include 依存関係を減らすことが可能になります:
// MyStruct.h内 #include <iosfwd> // std::ostreamの前方宣言を含む struct MyStruct { int value; friend std::ostream& operator<<(std::ostream& os, const S& s); // 定義はMyStruct.cppファイルで提供され、#include <ostream>を使用 };
前方宣言がローカルスコープに現れた場合、それは以前に宣言されたクラス、変数、関数、および外側のスコープに現れる可能性のある同じ名前のすべての宣言を 隠蔽 します:
struct s { int a; }; struct s; // 何もしない(このスコープではsは既に定義済み) void g() { struct s; // 新しいローカル構造体"s"の前方宣言 // これにより、このブロックの終了までグローバル構造体sが隠蔽される s* p; // ローカル構造体sへのポインタ struct s { char* p; }; // ローカル構造体sの定義 }
新しいクラス名は、 elaborated type specifier によって導入されることもあります。これは他の宣言の一部として現れますが、 name lookup が同じ名前を持つ以前に宣言されたクラスを見つけられない場合に限ります。
class U; namespace ns { class Y f(class T p); // 関数ns::fを宣言し、ns::Tとns::Yを宣言する class U f(); // Uは::Uを参照する // TとYへのポインタと参照を使用可能 Y* p; T* q; }
メンバー仕様
メンバー仕様、またはクラス定義の body は、以下の中から任意の数の要素を中括弧で囲んだシーケンスです:
attr
(optional)
decl-specifier-seq
(optional)
member-declarator-list
(optional)
;
|
|||||||||
| attr | - | (C++11以降) 任意の数の 属性 |
| decl-specifier-seq | - | 指定子 のシーケンス。コンストラクタ、デストラクタ、およびユーザー定義型の 変換関数 の宣言でのみ省略可能 |
| member-declarator-list | - |
init-declarator-list
と類似しているが、追加で
ビットフィールド宣言
、
pure-specifier
、およびvirt-specifier(
override
または
final
)
(C++11以降)
を許可し、
direct-non-list-initialization構文
は許可しない
|
この宣言は static および非staticの データメンバ と メンバ関数 、メンバ typedef 、メンバ 列挙型 、および ネストされたクラス を宣言できる。また friend宣言 にもなり得る。
class S { int d1; // non-static data member int a[10] = {1, 2}; // non-static data member with initializer (C++11) static const int d2 = 1; // static data member with initializer virtual void f1(int) = 0; // pure virtual member function std::string d3, *d4, f2(int); // two data members and a member function enum { NORTH, SOUTH, EAST, WEST }; struct NestedS { std::string s; } d5, *d6; typedef NestedS value_type, *pointer_type; };
class M { std::size_t C; std::vector<int> data; public: M(std::size_t R, std::size_t C) : C(C), data(R*C) {} // constructor definition int operator()(std::size_t r, std::size_t c) const // member function definition { return data[r * C + c]; } int& operator()(std::size_t r, std::size_t c) // another member function definition { return data[r * C + c]; } };
public:
、
protected:
、および
private:
class S { public: S(); // public constructor S(const S&); // public copy constructor virtual ~S(); // public virtual destructor private: int* ptr; // private data member };
class Base { protected: int d; }; class Derived : public Base { public: using Base::d; // BaseのprotectedメンバdをDerivedのpublicメンバにする using Base::Base; // すべての基底クラスのコンストラクタを継承する (C++11) };
static_assert
宣言:
template<typename T> struct Foo { static_assert(std::is_floating_point<T>::value, "Foo<T>: T must be floating point"); };
struct S { template<typename T> void f(T&& n); template<class CharT> struct NestedS { std::basic_string<CharT> s; }; };
| (C++11以降) |
`タグ内のC++コードは翻訳せず保持
- HTMLタグ、属性、クラス名は全て保持
- 書式設定は完全に維持
|
8)
デダクションガイド
のメンバークラステンプレート:
struct S { template<class CharT> struct NestedS { std::basic_string<CharT> s; }; template<class CharT> NestedS(std::basic_string<CharT>) -> NestedS<CharT>; }; |
(C++17以降) |
| (C++20以降) |
ローカルクラス
関数本体の内部でクラス宣言を記述することができ、その場合 local class を定義します。このようなクラスの名前は関数スコープ内でのみ存在し、外部からはアクセスできません。
- ローカルクラスのメンバーは、そのクラスの定義内でのみ宣言できます。ただし、 ネストされたクラス のメンバーは、そのクラスの最も近い外側の ブロックスコープ でも宣言できます。
- ローカルクラス内にネストされたクラスもローカルクラスです。
- ローカルクラスは静的データメンバーを持つことができません。
- ローカルクラスのメンバー関数はリンケージを持ちません。
- ローカルクラスのメンバー関数は、クラス本体内部で完全に定義する必要があります。
- ローカルクラスは クロージャ型 以外 (C++14以降) はメンバーテンプレートを持つことができません。
- ローカルクラスは フレンドテンプレート を持つことができません。
- ローカルクラスはクラス定義内で フレンド関数 を定義できません。
- 関数(メンバー関数を含む)内のローカルクラスは、外側の関数がアクセスできる同じ名前にアクセスできます。
|
(until C++11) |
#include <algorithm> #include <iostream> #include <vector> int main() { std::vector<int> v{1, 2, 3}; struct Local { bool operator()(int n, int m) { return n > m; } }; std::sort(v.begin(), v.end(), Local()); // since C++11 for (int n : v) std::cout << n << ' '; std::cout << '\n'; }
出力:
3 2 1
キーワード
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 1693 | C++98 | メンバー宣言を空にできなかった | 空の宣言が許可される |
| CWG 1930 | C++98 |
member-declarator-list
が空の場合がありえた(
decl-specifier-seq
にストレージクラス指定子またはCV修飾子が含まれる場合) |
リストは空であってはならない |
| CWG 2890 | C++98 | ネストされたクラスのメンバーをどこで宣言できるか不明確だった | 明確化された |
関連項目
|
C ドキュメント
for
Struct 宣言
|