0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

operator+していないのに演算できてしまう

Last updated at Posted at 2021-12-28

演算子のオーバーロードの動作確認で以下のコードを実行してみた。
operator+(int) は if 0 しておく。

operator.cpp
#include<iostream>
class myInteger {
    int value;
public:
    int operator + ( myInteger obj ) {
        return this->value + obj.value;
    }
#if 0
    int operator + ( int num ) {
        return this->value + num;
    }
#endif
    myInteger(int value) { this->value = value; }
};

int main() {
    myInteger obj1(10), obj2(50);
    int num = 5;

    std::cout << obj1 + obj2 << std::endl;
    std::cout << obj1 + num  << std::endl;

    return 0;
}

結果は、

root@2af9a6fb2cb6:/cpp/operatpr# g++ -g -O0 operator.cpp
root@2af9a6fb2cb6:/cpp/operatpr# ./a.out
60
15
root@2af9a6fb2cb6:/cpp/operatpr#

ん?実行できちゃった。
obj1 + num はコンパイル時か実行時にエラーになると思ったのだけれど。

gdb でも確認してみる。

(gdb) p obj1 + obj2
$1 = 60
(gdb) p obj1 + num
Cannot resolve function operator+ to any overloaded instance
(gdb) p obj1 + 5
Cannot resolve function operator+ to any overloaded instance
(gdb)

こちらは予想通り。
ちなみに、operator.cpp の if 0 を有効にした場合は、

(gdb) p obj1 + obj2
$1 = 60
(gdb) p obj1 + num
$2 = 15
(gdb) p obj1 + 5
$3 = 15
(gdb)

となり、これは想定通りの動作。
もうちょっと調べてみる。


コメントで丁寧に教えていただきました。
ありがとうございます。

原因:暗黙の型変換によるもの

暗黙の型変換で使われているコンストラクタをecplicit 修飾で修飾する

    explicit myInteger(int value) { this->value = value; }

operator.cpp: In function 'int main()':
operator.cpp:21:23: error: no match for 'operator+' (operand types are 'myInteger' and 'int')
std::cout << obj1 + num << std::endl;
~~~~~^~~~~
operator.cpp:5:9: note: candidate: int myInteger::operator+(myInteger)
int operator + ( myInteger obj ) {
^~~~~~~~
operator.cpp:5:9: note: no known conversion for argument 1 from 'int' to 'myInteger'

コンパイルで弾かれた。当初期待していた動作となった。

左辺も受け取りたい

メンバ関数での演算子のオーバーロードでは引数は1つしか受け取れない。
メンバ関数ではprivateメンバにアクセスできるようにしておいて、
非メンバ関数で2項を受け取る関数を定義する

class myInteger {
    int value;
public:
    myInteger &operator +=(const myInteger &r) {
        value += r.value;
        return *this;
    }
    myInteger &operator +=(int r) {
        value += r;
        return *this;
    }
    explicit myInteger(int value) { this->value = value; }
};

// クラス同士
const myInteger operator+(const myInteger& l, const myInteger& r) {
    return myInteger(l) += r;
}
// 左辺がint
const myInteger operator+(int l, const myInteger& r) {
    return myInteger(r) += l;
}
// 右辺がint
const myInteger operator+(const myInteger& l, int r) {
    return myInteger(l) += r;
}
0
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?