C++の演算子のオーバーロード機能を使ってみた

C++の演算子のオーバーロード機能を試してみたので簡単にメモとして残しておきます。

よく使われる演算の簡潔な表記の重要性は、計り知れないほど大きい。ほとんどの言語と同様に、C++は組み込みデータ型のために一連の演算子を提供している。しかし、それらの演算子を使うと便利な概念は、C++の組み込みデータ型に限られるものではない。ユーザー定義型でも使えなければならないのである。
(プログラミング言語C++ 第3版 「第11章 演算子の多重定義」より)

演算子は+-*/%などの演算を行うための記号です。 1+1であれば、+演算子は1に1を加算するという意味になります。 a+=bはaにbを加算した値をaに代入するという意味になります。 このaやbが整数型(int)であれば話は簡単です。単純な整数値の加算になります。

ではaやbが独自に作成したクラスの型だったらどうでしょう。コンパイラはユーザーが作成したクラスオブエクト同士の+演算子を用いた演算方法を知りません。そのためコンパイルエラーとなります。

ここで演算子のオーバーロードの登場です。 つまり、独自クラス同士、あるいは独自クラスと他の型を+で演算した場合の処理を定義し、+演算子の左側や右側に来る型に応じて適切な演算が行われるように+記号をオーバーロードさせるというのが演算子のオーバーロードです。

先ほどのa+=bは関数を用いて演算する場合は、a.plus(b)のような関数を定義することもできます。aやbがX型であれば以下のようなクラスになります。

class X {
public:
    int x;
    X& plus(X a) { //インスタンス変数のxと引数に渡されたXインスタンスのxを加算して自身の参照を返す
        x += a.x;
        return *this;
    }
};

演算子をオーバーロードするためには、このplus()のような関数の代わりにoperatorという関数を使用します。ポイントはこのoperatorの後にオーバーロードしたい演算子を指定する点です。

operatorオーバーロードしたい演算子()

+=演算子をオーバーロードする場合は以下のように書き直せばOKです。

class X {
public:
    int x;
    X& operator+=(X a) {
        x += a.x;
        return *this;
    }
};

実際に+=演算子を用いてXオブジェクト同士を演算してみましょう。

int main () {

    X a = X();
    X b = X();
    a.x = 5;
    b.x = 3;

    a += b; //a.operator+=(b)の呼び出しになる
    cout << "a.x=" << a.x << endl;

    return 0;
}

出力は、

a.x=8

になります。

ちなみにoperator関数をクラス定義の外で定義する場合は、演算対象(左辺値と右辺値)の両方を引数に渡します。 また、operator関数内で他のoperator関数を呼び出すことも可能です。

X operator+(X a, X b) {
    X& r = a;
    return r += b; //a.operator+=(b)の呼び出しになる
}

以下のようにXオブジェクト同士を+演算子を用いて演算できるようになりました。

    X c = X();
    c = a + b; //operator+(a, b)の呼び出し
    cout << "c.x=" << c.x << endl;

演算子のオーバーロードは必須ではありませんが、使用することでコードがシンプルになり、視認性も向上しますね。

今回参考にした書籍

公開日:2020年11月14日
最終更新日:2022年09月12日

他の記事も見る

このページのトップに戻る