【C++】独自classで演算子のオーバーロードをする方法を初心者向けに解説

[記事内には広告が含まれています]

こんにちは、現役エンジニアの inno_tech です。

C++で独自class同士の足し算・引き算等を行う方法をお探しでしょうか? C++では演算子オーバーロードを使うことで実現できます。(オペレーターのオーバーロードとも呼ばれます。)

本記事を読めば、初心者でも演算子オーバーロードを使いこなせるようになります

サンプルコードは Ubuntu18.04で動作確認を行っています。

もくじ

演算子オーバーロード機能とは?

C++では、算術演算+,-,+,/等値演算子==, !=やといった演算子に対し、独自の振る舞いを定義することが可能です。この独自の振る舞いを定義しなおす(上書きする)ことを「演算子オーバーロード」と呼びます。

具体的な活用シーンとしては、class同士の演算でよく使用されます。

演算子オーバーロードがない場合、classオブジェクト同士の足し算はできません。したがって、専用の関数を用意するといった対応が必要です。

しかし、演算子オーバーロードを使えばa+bのような簡潔な記述で演算を行えるようになります。

多くのオープンソースライブラリでも実装されてるテクニックです。

見たほうが早いので、サンプルコードで説明します。

サンプルコード | 算術演算子のオーバーロード

3次元空間のベクトルを意味するvector3Dという独自classを定義し、その中で算術演算子(+)をオーバーロードするサンプルで説明します。

サンプルコード | 独自class内に演算子オーバーロードを定義

まずは独自class vector3Dを定義します。このクラスではx, y, zの各ベクトル成分をメンバー変数として持っています。

今回は算術演算子の中でも ++=に対してオーバーロードを定義しました。このオーバーロードにより、x, y, z3つの変数を一括で足し算でき、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 [演算子](引数){ 処理; }という形式で演算子をオーバーロードします。

引数は参照型(&)で渡すのがおすすめ。値渡しの場合、変数が内部コピーされるからパフォーマンスが落ちるよ。

a+bのように書いた場合、aには、thisポインタでアクセスします。一方、bは引数として渡されます

サンプルコード | 演算子オーバーロードの結果を確認

続いて、先ほど定義した演算子オーバーロードが正しく動作するか確認します。

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を設計できるようになりますよ。

あわせて読みたい
【サンプル付き】C++ クラステンプレートの使い方を解説 C++のクラステンプレート(class template)の使い方についてお困りでしょうか?今回は、クラステンプレートの使い方をサンプルコードを交えながら解説します。 本記事を...

最後に、わかりやすいコードを書くためのおすすめ書籍がこちらです。Qiita等でも多くのプログラマに絶賛されていて、私自身もこの書籍を参考したらコードの品質がかなり安定してきました。

話は変わりますが、プログラミングを習得したい, 仲間が欲しい人は、プログラミングスクールに通うのがおすすめです
自己学習でかかるコストを考えると十分元が取れると思います。

少しでも興味があれば、まずは無料のオリエンテーションを受講し、自分に合うか試してみるのがよいでしょう。

まずは一歩行動して、将来の自分に楽をさせてあげましょう。

いかがだったでしょうか。
ほかにも役立つ情報が他のページにもあるかもしれません。
ご覧いただくかはあなた次第です!

この記事がイイねと思ったら、Twitterフォロー か  にほんブログ村のどちらかしてくれたら嬉しいよ!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!

コメント / ご要望

コメントする

goto
もくじ
閉じる