名前空間
変種
操作

クラス宣言

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)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

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

クラスはユーザー定義型であり、宣言構文のdecl-specifier-seqに現れるclass-specifierによって定義されます。

目次

[編集] 構文

クラス指定子は以下の構文を持ちます。

class-key attr (省略可能) class-head-name class-property-specs (省略可能) base-clause (省略可能)
{ member-specification }
(1)
class-key attr (省略可能) base-clause (省略可能)
{ member-specification }
(2)
1) 名前付きクラス定義
2) 匿名クラス定義
class-key - classstructunionのいずれか。classstructキーワードは、デフォルトのメンバーアクセスとデフォルトの基底クラスアクセスを除いて同一です。unionの場合、この宣言は共用体型を導入します。
attr - (C++11以降) 任意の数の属性alignas指定子を含むことができます。
class-head-name - 定義されているクラスの名前。修飾されることも可能です。
class-property-specs - 以下の指定子のリスト。各指定子は各シーケンスで最大1回まで許可されます。
指定子 効果
final
(C++11以降)
そのクラスが派生できないことを指定します。
trivially_relocatable_if_eligible     
(C++26以降)
条件を満たしていれば、クラスを自明に再配置可能としてマークします。
replaceable_if_eligible     
(C++26以降)
条件を満たしていれば、クラスを置換可能としてマークします。
base-clause - 1つ以上の基底クラスと、それぞれの継承モデルのリスト(派生クラスを参照)。
member-specification - アクセス指定子、メンバーオブジェクトおよびメンバー関数の宣言と定義のリスト(以下を参照)。

[編集] 前方宣言

以下の形式の宣言

class-key attr identifier ;

後でこのスコープ内で定義されるクラス型を宣言します。定義が現れるまで、このクラス名は不完全型です。これにより、相互参照するクラスが可能になります。

class Vector; // forward declaration
 
class Matrix
{
    // ...
    friend Vector operator*(const Matrix&, const Vector&);
};
 
class Vector
{
    // ...
    friend Vector operator*(const Matrix&, const Vector&);
};

特定のソースファイルがクラスへのポインタと参照のみを使用する場合、これにより#includeの依存関係を減らすことができます。

// In MyStruct.h
#include <iosfwd> // contains forward declaration of std::ostream
 
struct MyStruct
{
    int value;
    friend std::ostream& operator<<(std::ostream& os, const S& s);
    // definition provided in MyStruct.cpp file which uses #include <ostream>
};

前方宣言がローカルスコープに現れる場合、それは以前に宣言されたクラス、変数、関数、および囲むスコープに現れる可能性のある同じ名前の他のすべての宣言を隠蔽します。

struct s { int a; };
struct s; // does nothing (s already defined in this scope)
 
void g()
{
    struct s; // forward declaration of a new, local struct "s"
              // this hides global struct s until the end of this block
 
    s* p; // pointer to local struct s
 
    struct s { char* p; }; // definitions of the local struct s
}

新しいクラス名は、別の宣言の一部として現れるelaborated type specifierによっても導入されうることに注意してください。ただし、その場合、名前検索が同じ名前で以前に宣言されたクラスを見つけられない場合に限ります。

class U;
 
namespace ns
{
    class Y f(class T p); // declares function ns::f and declares ns::T and ns::Y
 
    class U f(); // U refers to ::U
 
    // can use pointers and references to T and Y
    Y* p;
    T* q;
}

[編集] メンバー仕様

メンバー仕様、またはクラス定義の本体は、以下の任意の数の波括弧で囲まれたシーケンスです。

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以降)を許可し、direct-non-list-initialization構文は許可しません。

この宣言は、staticおよび非staticデータメンバーメンバー関数、メンバーtypedef、メンバー列挙、およびネストされたクラスを宣言できます。また、フレンド宣言であることも可能です。

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;
};
2) メンバー関数またはフレンド関数の両方を宣言および定義する関数定義。メンバー関数定義の後のセミコロンは省略可能です。クラス本体内で定義されるすべての関数は、inlineとなり、名前付きモジュールにアタッチされていない限り(C++20以降)
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];
    }
};
3) アクセス指定子 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
};
4) using-declaration
class Base
{
protected:
    int d;
};
 
class Derived : public Base
{
public:
    using Base::d;    // make Base's protected member d a public member of Derived
    using Base::Base; // inherit all bases' constructors (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;
    };
};
7) エイリアス宣言
template<typename T>
struct identity
{
    using type = T;
};
(C++11以降)
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以降)
9) using-enum-declaration
enum class color { red, orange, yellow };
 
struct highlight
{
    using enum color;
};
(C++20以降)

[編集] ローカルクラス

クラス宣言は関数本体の内部に現れることができ、その場合、それはローカルクラスを定義します。そのようなクラスの名前は関数スコープ内でのみ存在し、外部からはアクセスできません。

  • ローカルクラスのメンバーは、そのクラスの定義内でのみ宣言できます。ただし、ネストされたクラスであるメンバーは、そのクラスの最も近い囲むブロックスコープ内でも宣言できます。
  • ローカルクラス内にネストされたクラスもローカルクラスです。
  • ローカルクラスは静的データメンバーを持つことができません。
  • ローカルクラスのメンバー関数はリンケージを持ちません。
  • ローカルクラスのメンバー関数は、クラス本体内で完全に定義されなければなりません。
  • ローカルクラスは、クロージャ型を除く(C++14以降)、メンバーテンプレートを持つことができません。
  • ローカルクラスはフレンドテンプレートを持つことができません。
  • ローカルクラスは、クラス定義内でフレンド関数を定義できません。
  • 関数(メンバー関数を含む)内のローカルクラスは、囲む関数がアクセスできるのと同じ名前にアクセスできます。
  • ローカルクラスはテンプレート引数として使用できませんでした。
(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

[編集] キーワード

class, struct, union

[編集] 欠陥報告

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

DR 適用対象 公開された動作 正しい動作
CWG 1693 C++98 メンバー宣言は空であってはいけません 空の宣言が許可されました
CWG 1930 C++98 decl-specifier-seqがストレージクラス指定子またはcv修飾子を含む場合、member-declarator-listは空であってもよい
ストレージクラス指定子またはcv修飾子を含む場合
リストは空であってはなりません
CWG 2890 C++98 ネストされたクラスのメンバーがどこで宣言できるかが不明瞭でした 明確化された

[編集] 関連項目

C ドキュメント構造体宣言について)
English 日本語 中文(简体) 中文(繁體)