クラス宣言
提供: cppreference.com
クラスおよび構造体は、クラス指定子によって定義される、ユーザ定義の型です。 クラス指定子は宣言の構文の decl-specifier-seq 内に現れます。 クラス指定子は以下の構文を持ちます。
class-key attr class-head-name base-clause { member-specification }
|
|||||||||
| class-key | - | class または struct のいずれか。 これらのキーワードは、デフォルトのメンバアクセスとデフォルトの基底クラスアクセスを除いて、同じです。 |
| attr(C++11) | - | オプショナルな任意個の属性の並び。 alignas 指定子を含んでも構いません。 |
| class-head-name | - | 定義されるクラスの名前。 修飾付きでも構いません。 キーワード final を後に続けても構いません。 名前は省略しても良く、その場合クラスは無名です (無名クラスは final にできないことに注意してください)。 |
| base-clause | - | オプショナルな1個以上の親クラスと使用される継承モデルのリスト (派生クラスを参照してください)。 |
| member-specification | - | アクセス指定子、メンバオブジェクトおよびメンバ関数の宣言と定義のリスト (下を参照)。 |
構文の一般的な概要はクラスを参照してください。 class-key が union の場合、その宣言は共用体型を導入します。
前方宣言
以下の形式の宣言は、
class-key attr identifier ;
|
|||||||||
そのスコープで後ほど定義されるであろうクラス型を宣言します。 定義が現れるまで、そのクラス名は不完全型です。 これは複数のクラスがお互いを参照することを可能とします。
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);
// 定義は #include <ostream> を使用する MyStruct.cpp ファイル内で提供されます。
};
前方宣言がローカルスコープに現れた場合、それは囲っているスコープ内に現れた同じ名前の以前に宣言されたクラス、変数、関数、およびその他のすべての宣言を隠蔽します。
struct s { int a; };
struct s; // 何もしません (s はこのスコープですでに定義されています)。
void g() {
struct s; // 新しいローカルな構造体「s」の前方宣言。
// これはグローバルな構造体 s をこのブロックの終わりまで隠蔽します。
s* p; // ローカルな構造体 s へのポインタ。
struct s { char* p; }; // ローカルな構造体 s の定義。
}
新しいクラス名は別の宣言の一部として現れる複雑型指定子によっても導入されますが、名前探索が以前に宣言された同じ名前のクラスを発見できない場合のみであることに注意してください。
class U;
namespace ns{
class Y f(class T p); // 関数 ns::f を宣言し、クラス ns::T および ns::Y を宣言します。
class U f(); // U は ::U を参照します。
Y* p; T* q; // T および Y へのポインタおよび参照を使用できます。
}
メンバ指定
メンバ指定 (またはクラス定義の本体) は、波括弧で囲まれた任意個の以下の並びです。
1) 以下の形式のメンバ宣言。
attr(オプション) decl-specifier-seq(オプション) member-declarator-list(オプション) ;
|
|||||||||
| attr(C++11) | - | オプショナルな任意個の属性の並び。 |
| decl-specifier-seq | - | 指定子の並び。 コンストラクタ、デストラクタ、およびユーザ定義の型変換関数でのみオプショナルです。 |
| member-declarator-list | - | init-declarator-list と同様ですが、追加でビットフィールド宣言、純粋指定子、および virt-specifier (override または final) (C++11以上) が使用でき、直接非リスト初期化の構文は使用できません。
|
この宣言は静的および非静的なデータメンバ、メンバ関数、メンバ typedef、メンバ列挙、およびネストしたクラスを宣言できます。 また、フレンド宣言であっても構いません。
class S {
int d1; // 非静的データメンバ。
int a[10] = {1,2}; // 初期化子付きの非静的データメンバ (C++11)。
static const int d2 = 1; // 初期化子付きの静的データメンバ。
virtual void f1(int) = 0; // 純粋仮想メンバ関数。
std::string d3, *d4, f2(int); // 2個のデータメンバと1個のメンバ関数。
enum {NORTH, SOUTH, EAST, WEST};
struct NestedS {
std::string s;
} d5, *d6;
typedef NestedS value_type, *pointer_type;
};
2) 関数定義。 メンバ関数またはフレンド関数の宣言と定義を両方します。 メンバ関数定義の後のセミコロンはオプショナルです。 クラス本体内で定義されたすべての関数は自動的にインラインです。
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) {} // コンストラクタの定義。
int operator()(size_t r, size_t c) const { // メンバ関数の定義。
return data[r*C+c];
}
int& operator()(size_t r, size_t c) { // 別のメンバ関数の定義。
return data[r*C+c];
}
};
3) アクセス指定子
public:、 protected:、および private:。
class S {
public:
S(); // public コンストラクタ。
S(const S&); // public コピーコンストラクタ。
virtual ~S(); // public 仮想デストラクタ。
private:
int* ptr; // private データメンバ。
};
4) using 宣言。
class Base {
protected:
int d;
};
class Derived : public Base {
public:
using Base::d; // Base の protected メンバ d を Derived の public メンバにします。
using Base::Base; // 親のすべてのコンストラクタを継承します (C++11)。
};
5) static_assert 宣言。
template<typename T>
struct Foo {
static_assert(std::is_floating_point<T>::value, "Foo<T>: T must be floating point");
};
6) メンバテンプレート宣言。
struct S {
template<typename T>
void f(T&& n);
template<class CharT>
struct NestedS {
std::basic_string<CharT> s;
};
};
|
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++14以上)ローカルクラスはメンバテンプレートを持つことはできません。
- ローカルクラスはフレンドテンプレートを持つことはできません。
- ローカルクラスはクラス定義内でフレンド関数を定義することはできません。
- 関数 (メンバ関数を含みます) 内のローカルクラスは囲っている関数がアクセスできるものと同じ名前にアクセスできます。
|
(C++11未満) |
Run this code
#include <vector>
#include <algorithm>
#include <iostream>
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()); // C++11以上。
for(int n: v) std::cout << n << ' ';
}
出力:
3 2 1
関連項目
構造体宣言 の C言語リファレンス
|