Namespaces
Variants

Class declaration

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Class/struct types
Union types

Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

クラスはユーザー定義型であり、クラス指定子によって定義されます。クラス指定子は 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)
1) 名前付きクラス定義
2) 無名クラス定義
class-key - class struct union のいずれか。 class struct は、デフォルトの メンバーアクセス とデフォルトの 基底クラスアクセス を除いて同一です。 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 ;

このスコープ内で後ほど定義されるクラス型を宣言します。定義が現れるまで、このクラス名は 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 は、以下の中から任意の数の要素を中括弧で囲んだシーケンスです:

1) 以下の形式のメンバー宣言
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;
};
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宣言 :
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;
    };
};
7) エイリアス宣言 :
template<typename T>
struct identity
{
    using type = T;
};
(C++11以降)
翻訳内容: - "alias declarations" → "エイリアス宣言" - "(since C++11)" → "(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以降)
9) using-enum宣言 :
enum class color { red, orange, yellow };
struct highlight
{
    using enum color;
};
(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

キーワード

class struct union

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

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

関連項目

C ドキュメント for Struct 宣言