クラス

スポンサーリンク

クラス

クラス (class) は,メンバ変数,メンバ関数などをメンバに持つデータ型で,次のように定義します。
最後にセミコロンが必要なのは,C の構造体と同様,クラスの定義と同時にオブジェクトの定義も可能なためです。

class クラス名
{
    メンバの宣言
};

次のプログラムは,時計を表す Clock クラスを定義したものです。

#include <cstdio>

// Clock クラスの定義
class Clock
{
public:
    int hour;
    int minute;
    void set(int hour, int minute);
    void print();
};

void Clock::set(int hour, int minute)
{
    this->hour = hour % 24;
    this->minute = minute % 60;
}

void Clock::print()
{
    printf("%02d:%02d\n", hour, minute);
    fflush(stdout);
}

int main()
{
    Clock c;    // インスタンス化
    c.set(6, 30);
    c.print();  // 出力: 06:30
}

時計を表すクラス Clock の具現化である c は,Clock クラスのインスタンス (instance) またはオブジェクト (object) と呼ばれます。
## メンバ変数の初期化

クラス定義内で,static const でないメンバ変数を int hour = 0; のように初期化することは禁止されています。
メンバ変数を初期化する方法については,コンストラクタの説明と共に説明します。

メンバ関数の定義

今回の Clock クラスでは,クラス定義の中にはメンバ関数の宣言のみを書き,関数の定義はクラス定義の外に記述しました。
関数定義 void Clock::set(...) { ... } における記号 :: は,スコープ解決演算子です。

関数定義が短い場合,関数定義をクラス定義の中に直接記述することもあります。
この方法で書かれた関数はインライン関数と呼ばれ,コンパイル時にインライン展開されます。

class Clock
{
public:
    int hour;
    int minute;
    void set(int hour, int minute) { /* ... */ }
    void print() { /* ... */ }
};

this ポインタ

クラス内部では,自身のオブジェクトへのポインタである this ポインタが利用できます。

今回の set 関数のように,メンバ hour と仮引数 hour の名前が重複した場合,前者を this->hour,後者を hour と書き分けて区別することができます。

アクセス指定子

Clock クラスのメンバ変数 hour, minute をクラスの外部からアクセス不能にするには,次のようにアクセス指定子 private を指定します。
このようにすれば,c.hour = -64 などと不正な値が設定されるのを防ぐことができます。

class Clock
{
private:
    int hour;            // 非公開
    int minute;          // 非公開
public:
    void set(int, int);  // 公開
    void print();        // 公開
};

アクセス指定子には,public, private, protected の 3 つがあります。

アクセス指定子説明
publicクラスの内部および外部からアクセス可能
privateクラスの内部からのみアクセス可能
protected派生クラスを含むクラスの内部からのみアクセス可能

クラスにおいてアクセス指定子を省略した場合は,private アクセスレベルが適用されます。

class Clock
{
    int hour;            // 非公開
    int minute;          // 非公開
public:
    void set(int, int);  // 公開
    void print();        // 公開
};

フレンド

フレンド (friend) とは,特定の関数やクラスに対して,あるクラスの非公開メンバへのアクセス権を与える機能です。

次のプログラムは,クラス Class1 について func1() をフレンド関数に,ClassFriend をフレンドクラスに指定したものです。

class Class1
{
private:
    friend void func1(Class1&);  // フレンド関数
    friend class ClassFriend;    // フレンドクラス
    int num;
};

void func1(Class1& c)
{
    c.num = 123;
}
class ClassFriend
{
public:
    static void func2(Class1& c) { c.num = 456; }
};

int main()
{
    Class1 c;
    func1(c);
    ClassFriend::func2(c);
}

静的メンバ

宣言に static を付けたメンバは静的メンバと呼ばれ,クラスをインスタンス化せずに利用できます。

次のプログラムは,静的メンバ n, func1 を持つクラスを定義したものです。

class Class1
{
public:
    static int n;  // 静的メンバ変数の宣言
    static void func1() { }
};

// 静的メンバ変数の定義
int Class1::n = 1;

int main()
{
    Class1::n;
    Class1::func1();
}

静的メンバにアクセスするには,Class1::n のように,クラス名::メンバ名 と書きます。
ただし,c が Class1 クラスのインスタンスであるとき,c.n のように呼び出してもいいです。

const でない静的メンバ変数は,クラス定義内に書く宣言とは別に,クラス定義の外側に定義を書かなければなりません。
定義において初期化子を省略した場合,大域変数と同様 0 に初期化されます。

構造体とクラスの違い

C++ では,構造体とクラスとの間に本質的な違いはありません。
構造体は,クラスと同様にメンバ関数を持つことができ,クラスと同様に継承が可能です。

構造体とクラスの唯一の違いは,構造体のデフォルトアクセスレベルが public なのに対し,クラスのデフォルトアクセスレベルが private であることです。

class Class1
{
    void f();  // 非公開
public:
    void g();  // 公開
};
class Struct1
{
    void f();  // 公開
private:
    void g();  // 非公開
};
スポンサーリンク