前回はクラス同士の加算の結果を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に入っている
となりました。
このような計算も「演算子オーバーロード」を使う事で簡単に出来ます。
次回は注意点を書きます。