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


前回はクラス同士の加算の結果をint型で返しましたが、別のケースを紹介します。

色々なクラスを作っていると、演算結果をクラスで返したい場合も多く出てきます。

ゲームで頻繁に使われるベクトルのクラスなどは良い例で、様々な演算子がオーバーロードされています。

2Dベクトルのクラスの一部を作って試してみます。

<sample program cpp062-01>

#include <iostream>

class Vector2 {
public:

    Vector2(const int x, const int y);

private:

    int m_x;
    int m_y;
};

int main()
{
    Vector2 v1(5, 3);
    Vector2 v2(2, 6);

    return 0;
}

Vector2::Vector2(const int x, const int y) : m_x(x), m_y(y)
{

}

2Dベクトルクラスのメンバ変数はXとYです。

コンストラクタの初期化リストで初期値を代入しています。

ベクトルの加算はそれぞれのX同士を加算、Y同士を加算した結果をベクトルに格納するように作ります。

クラスなどでは無く、普通の変数で書いてみると、

x3 = x1 + x2;
y3 = y1 + y2;

と別々に計算するところを、ベクトルだと

v3 = v1 + v2;

と書くと、XもYも加算した結果が得られると言うようなイメージです。

※すみません、ちょっと分かりにくいですね・・・


実際に演算子オーバーロードを使って、ベクトル同士の加算を作ってみます。

<sample program cpp062-02>

#include <iostream>

class Vector2 {
public:

    Vector2(const int x, const int y);

    Vector2 operator+(const Vector2 &rhs) const;

private:

    int m_x;
    int m_y;
};

int main()
{
    Vector2 v1(5, 3);
    Vector2 v2(2, 6);

    return 0;
}

Vector2::Vector2(const int x, const int y) : m_x(x), m_y(y)
{

}

Vector2 Vector2::operator+(const Vector2 &rhs) const
{
    Vector2 temp;

    temp.m_x = m_x + rhs.m_x;
    temp.m_y = m_y + rhs.m_y;

    return temp;
}

まず、関数の戻り値はVector2クラスになっています。

関数本体では、作業領域(temp)を用意して、自分自身のm_xと右辺のm_xを加算した結果と、m_yと右辺のm_yを加算した結果を代入しています。

※tempとは「temporary」の略で「一時的な」という意味があり、よく使われる変数名です。

そして、m_xとm_yを加算した結果を格納したtempをreturnしています。

しかし、

Vector2 temp;

この時点でコンパイルエラーが発生しています。


どこでエラーになっているかと言うと、

Vector2 temp;

ここです。

以前書きましたが、引数のあるコンストラクタ関数を作ると「既定のコンストラクタ」が作られず、引数の無い実体は作れなくなります。

では、対処法として「既定のコンストラクタ」を作ります。

「既定のコンストラクタ」とは引数の無いコンストラクタ関数です。

<sample program cpp062-03>

#include <iostream>

class Vector2 {
public:

    Vector2();

    Vector2(const int x, const int y);

    Vector2 operator+(const Vector2 &rhs) const;

private:

    int m_x;
    int m_y;
};

int main()
{
    Vector2 v1(5, 3);
    Vector2 v2(2, 6);

    return 0;
}

Vector2::Vector2() : m_x(0), m_y(0)
{

}

Vector2::Vector2(const int x, const int y) : m_x(x), m_y(y)
{

}

Vector2 Vector2::operator+(const Vector2 &rhs) const
{
    Vector2 temp;

    temp.m_x = m_x + rhs.m_x;
    temp.m_y = m_y + rhs.m_y;

    return temp;
}

とりあえず、引数の無いコンストラクタ関数を作り、初期化リストで0を入れました。

これでエラーは無くなりました。


では、作った「+演算子」を使って加算をしてみます。

<sample program cpp062-04>

#include <iostream>

class Vector2 {
public:

    Vector2();

    Vector2(const int x, const int y);

    Vector2 operator+(const Vector2 &rhs) const;

private:

    int m_x;
    int m_y;
};

int main()
{
    Vector2 v1(5, 3);
    Vector2 v2(2, 6);

    Vector2 v3;

    v3 = v1 + v2;

    return 0;
}

Vector2::Vector2() : m_x(0), m_y(0)
{

}

Vector2::Vector2(const int x, const int y) : m_x(x), m_y(y)
{

}

Vector2 Vector2::operator+(const Vector2 &rhs) const
{
    Vector2 temp;

    temp.m_x = m_x + rhs.m_x;
    temp.m_y = m_y + rhs.m_y;

    return temp;
}

v3も「既定のコンストラクタ」で作られています。

この「v3」に「v1」と「v2」を加算した結果を入れました。

では、「v3」には何が入っているのでしょうか。

ベクトルの中身を表示する関数を追加して確かめてみましょう。

<sample program cpp062-05>

#include <iostream>

class Vector2 {
public:

    Vector2();

    Vector2(const int x, const int y);

    Vector2 operator+(const Vector2 &rhs) const;

    void Show() const;

private:

    int m_x;
    int m_y;
};

int main()
{
    Vector2 v1(5, 3);
    Vector2 v2(2, 6);

    Vector2 v3;

    v3 = v1 + v2;

    v3.Show();

    return 0;
}

Vector2::Vector2() : m_x(0), m_y(0)
{

}

Vector2::Vector2(const int x, const int y) : m_x(x), m_y(y)
{

}

Vector2 Vector2::operator+(const Vector2 &rhs) const
{
    Vector2 temp;

    temp.m_x = m_x + rhs.m_x;
    temp.m_y = m_y + rhs.m_y;

    return temp;
}

void Vector2::Show() const
{
    std::cout << "x = " << m_x << std::endl;
    std::cout << "y = " << m_y << std::endl;
}

<実行結果>

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

メンバ変数のm_xとm_yを表示する関数Showを作りました。

結果は、

 v1のm_xとv2のm_xを加算した「7」とv1のm_yとv2のm_yを加算した「9」がv3に入っている

となりました。


このような計算も「演算子オーバーロード」を使う事で簡単に出来ます。

次回は注意点を書きます。


次へ

戻る

目次へ