こんにちは、現役エンジニアの inno_tech です。
C++で独自class同士の足し算・引き算等を行う方法をお探しでしょうか? C++では演算子オーバーロードを使うことで実現できます。(オペレーターのオーバーロードとも呼ばれます。)
サンプルコードは Ubuntu18.04で動作確認を行っています。
演算子オーバーロード機能とは?
C++では、算術演算+,-,+,/
や 等値演算子==, !=
やといった演算子に対し、独自の振る舞いを定義することが可能です。この独自の振る舞いを定義しなおす(上書きする)ことを「演算子オーバーロード」と呼びます。
具体的な活用シーンとしては、class同士の演算でよく使用されます。
演算子オーバーロードがない場合、classオブジェクト同士の足し算はできません。したがって、専用の関数を用意するといった対応が必要です。
多くのオープンソースライブラリでも実装されてるテクニックです。
見たほうが早いので、サンプルコードで説明します。
サンプルコード | 算術演算子のオーバーロード
3次元空間のベクトルを意味するvector3D
という独自classを定義し、その中で算術演算子(+)をオーバーロードするサンプルで説明します。
サンプルコード | 独自class内に演算子オーバーロードを定義
まずは独自class vector3D
を定義します。このクラスではx, y, z
の各ベクトル成分をメンバー変数として持っています。
今回は算術演算子の中でも +
と +=
に対してオーバーロードを定義しました。このオーバーロードにより、x, y, z
の3つの変数を一括で足し算でき、3次元ベクトルの足し算が表現できます。
#include <stdio.h>
#include <iostream>
#include <ostream>
class Vector3D
{
public:
/* constructor */
Vector3D(double x, double y, double z)
{
x_ = x;
y_ = y;
z_ = z;
};
/* denstructor */
~Vector3D(){};
/* method: データの表示 */
void PrintData() const
{
std::cout << "PrintData(x,y,z) = (" << x_ << "," << y_ << "," << z_ << ")" << std::endl;
};
/* オペレータ演算子 += */
Vector3D operator += (const Vector3D &in) {
this->x_ += in.x_;
this->y_ += in.y_;
this->z_ += in.z_;
return (*this);
}
/* オペレータ演算子 + */
Vector3D operator + (const Vector3D &in) {
Vector3D out(
this->x_ + in.x_,
this->y_ + in.y_,
this->z_ + in.z_
);
return out;
}
protected:
/* member */
double x_; // X
double y_; // Y
double z_; // Z
};
解説 | 演算子オーバーロード
加算(+)のオペレータ演算子をオーバーロードしているのはこの部分です。
Vector3D operator + (const Vector3D &in){ 処理; }
サンプルからわかる通り、戻り値 oprerator [演算子](引数){ 処理; }
という形式で演算子をオーバーロードします。
引数は参照型(&)で渡すのがおすすめ。値渡しの場合、変数が内部コピーされるからパフォーマンスが落ちるよ。
サンプルコード | 演算子オーバーロードの結果を確認
続いて、先ほど定義した演算子オーバーロードが正しく動作するか確認します。
void TestOperator_001()
{
printf("** test1-A: オペレータ演算子+のオーバーライド **\n" );
Vector3D vec1(0.0, 5.0, 8.0);
Vector3D vec2(10.0, 10.0, 10.0);
/* log(入力) */
std::cout << "vec1:" << std::endl;
vec1.PrintData();
std::cout << "vec2:" << std::endl;
vec2.PrintData();
Vector3D vec_sum = vec1 + vec2;
/* log(出力) */
vec_sum.PrintData();
printf("** test1-B: オペレータ演算子+=のオーバーライド **\n" );
Vector3D vec3(0.0, 5.0, 8.0);
/* log(入力) */
std::cout << "vec2:" << std::endl;
vec2.PrintData();
std::cout << "vec3:" << std::endl;
vec3.PrintData();
vec3 += vec2;
/* log(出力) */
std::cout << "vec3 += vec2:" << std::endl;
vec3.PrintData();
return;
}
結果はこのようになります。
** test1-A: オペレータ演算子+のオーバーライド **
vec1:
PrintData(x,y,z) = (0,5,8)
vec2:
PrintData(x,y,z) = (10,10,10)
vec1 + vec2:
PrintData(x,y,z) = (10,15,18)
** test1-B: オペレータ演算子+=のオーバーライド **
vec2:
PrintData(x,y,z) = (10,10,10)
vec3:
PrintData(x,y,z) = (0,5,8)
vec3 += vec2:
PrintData(x,y,z) = (10,15,18)
どちらの演算子も、x, y, z
の各要素が足し算されました。正しく動作していますね。
他の演算子も同じ要領で定義すればいいよ~!
まとめ
今回のまとめです。
- 演算子オーバーロードは、独自classの四則演算や等値演算子の振る舞いを定義できる便利な機能。
- 演算子のオーバーロードは
戻り値 oprerator [演算子](引数){ 処理; }
という形式で定義する。 - 演算子オーバーロードにすることでコードが簡潔で分かりやすくなる。
ただしオーバーロードは直感的なふるまいだけに留めてね!
複雑な処理にすると、他の人が見てもわかりにくくなります!
また、クラステンプレート機能とも組み合わせることで、より便利なclassを設計できるようになりますよ。
最後に、わかりやすいコードを書くためのおすすめ書籍がこちらです。Qiita等でも多くのプログラマに絶賛されていて、私自身もこの書籍を参考したらコードの品質がかなり安定してきました。
話は変わりますが、プログラミングを習得したい, 仲間が欲しい人は、プログラミングスクールに通うのがおすすめです。
自己学習でかかるコストを考えると十分元が取れると思います。
少しでも興味があれば、まずは無料のオリエンテーションを受講し、自分に合うか試してみるのがよいでしょう。
まずは一歩行動して、将来の自分に楽をさせてあげましょう。
いかがだったでしょうか。
ほかにも役立つ情報が他のページにもあるかもしれません。
ご覧いただくかはあなた次第です!
この記事がイイねと思ったら、Twitterフォロー か にほんブログ村のどちらかしてくれたら嬉しいよ!
コメント / ご要望