★演算子オーバーロード基礎1★


トランプのゲームを作ろうと思うと、カードの番号を加算したりしなければならないケースがあります。

例えばブラックジャックの場合、番号の合計を求め21を超えない数で21に近い方が勝ちます。

しかし、C++の変数はprivateに入っているケースが多く、合計を求めようとすると専用の関数が必要になります。

トランプのカードクラスを単純化したクラスの例を書きます。

<sample program cpp061-01>

#include <iostream>

class Card {
public:

    Card(const int suit, const int number);

private:

    int m_suit;
    int m_number;
};

int main()
{
    Card card1(0, 5);
    Card card2(1, 2);

    return 0;
}

Card::Card(const int suit, const int number) : m_suit(suit), m_number(number)
{

}

引数を持ったコンストラクタ関数を作り、初期値を与えた状態です。

この2枚のカードの番号を加算して合計値を求めたい場合、次のような関数になるでしょう。

<sample program cpp061-02>

#include <iostream>

class Card {
public:

    Card(const int suit, const int number);

    int Add(const Card &rhs);

private:

    int m_suit;
    int m_number;
};

int main()
{
    Card card1(0, 5);
    Card card2(1, 2);

    int sum = card1.Add(card2);

    std::cout << "sum = " << sum << std::endl;

    return 0;
}

Card::Card(const int suit, const int number) : m_suit(suit), m_number(number)
{

}

int Card::Add(const Card &rhs)
{
    return m_number + rhs.m_number;
}

<実行結果>

sum = 7
続行するには何かキーを押してください・・・

加算するための関数、Addを作りました。

本体を見ると、

int Card::Add(const Card &rhs)
{
    return m_number + rhs.m_number;
}

となっています。

呼び出し部分を見ると、

card1.Add(card2);

となっていますね。

クラスのメンバ関数ですから、カードクラスの実体であるcard1が関数を呼び出しています。

そして、引数としてcard2が渡されています。

card1の受け取りは「const参照」でrhs(右辺)という名前になっています。

大事な事は、同じCardクラスですから、お互いのprivateにアクセス出来ると言う事です。

card1のm_numberとrhs(card2)のm_numberを加算した結果をreturnしています。

これで、2つのクラスのメンバ変数m_numberの加算が出来ました。

Javaなどの言語では、このように加算関数を作ってメンバ変数同士を計算します。

しかし、C++にはもっと強力な機能が機能が用意されているのです。


演算子オーバーロード


その機能を「演算子オーバーロード」と言います。

関数のオーバーロードと同じく、演算子もオーバーロード出来るのです。

オーバーロードとは「多重定義」と言う意味でした。

同じ名前の関数に、異なる処理を割り当てる事が出来る機能です。

演算子も同じように、別の機能を持たせる事が出来るのです。

例えば、+演算子に色々な意味を持たせる事が出来ます。

※ただし、+演算子に減算や乗算など全くイメージの異なる機能を持たせる事はご法度です!

それでは、上のプログラムを演算子オーバーロードを使ったプログラムに変えてみます。

<sample program cpp061-03>

#include <iostream>

class Card {
public:

    Card(const int suit, const int number);

    int operator+(const Card &rhs) const;

private:

    int m_suit;
    int m_number;
};

int main()
{
    Card card1(0, 5);
    Card card2(1, 2);

    int sum = card1 + card2;

    std::cout << "sum = " << sum << std::endl;

    return 0;
}

Card::Card(const int suit, const int number) : m_suit(suit), m_number(number)
{

}

int Card::operator+(const Card &rhs) const
{
    return m_number + rhs.m_number;
}

<実行結果>

sum = 7
続行するには何かキーを押してください・・・

結果はAdd関数を使った時と同じです。


まずはプロトタイプ宣言を見ましょう。

int operator+(const Card &rhs) const;

最初は分かりにくいかも知れませんが、関数と同じように考えて大丈夫です。

int型を返す、「opeartor+」という関数で、引数としてCardクラスの「const参照」を受け取ります。

メンバ変数は書き換えませんので、後ろに「const」も付いています。

この「関数」はクラスの実体の後ろに「+」と書いた時点で呼び出され、右辺が引数として渡されます。

本体を見ると、

int Card::operator+(const Card &rhs) const
{
    return m_number + rhs.m_number;
}

前のAdd関数と変わりません。

しかし、呼び出している箇所を見ると、

int sum = card1 + card2;

関数呼び出しには見えず、単純に加算しているように見えます。

こちらの方が直観的で非常に分かりやすいです!

この「演算子オーバーロード」は様々な場面で役に立つ機能ですので、ぜひ習得して欲しい機能の1つです。

※Javaでは使えませんが、C#では使えます!


次へ

戻る

目次へ