Страницы

Поиск по вопросам

воскресенье, 7 апреля 2019 г.

Когда вызывается оператор преобразования типов?

#include using namespace std;
class three_d { int x, y, z; public: three_d(int a, int b, int c) {x=a; y=b, z=c; } three_d operator+(three_d op2); friend ostream &operator<<(ostream &stream, three_d &obj); operator int() {return x*y*z;} }; ostream &operator<< (ostream &stream, three_d &obj) { stream << obj.x << ", "; stream << obj.y << ", "; stream << obj.z << endl; return stream; } three_d three_d::operator+ (three_d op2) { x+=op2.x; y+=op2.y; z+=op2.z; return *this; }
int main() { three_d a(1, 2, 3), b(2, 3, 4); cout << a << b; cout << b+100 << endl; //31 line cout << a+b << endl; // 32 system("pause"); return 0; } В 31 строчке объект b приводится к int, потому что справа значение int, но зачем в 32 строчке привидении работает после того как выполнился operator+? Ведь тут два объекта с обоих сторон, почему тогда вызывается функция преобразования или как оно там называется, да ещё и в конце?


Ответ

Проблема в том, что ваш объект суммы не lvalue. Для него нужно const
friend ostream &operator<<(ostream &stream, const three_d &obj);
Без const cout << a+b трактуется не как
operator<<(cout, a+b) // ostream &stream, three_d &obj
а как
operator<<(cout, (int)(a+b)) // ostream &stream, const int& i
Объект, не являющийся lvalue, не может быть использован с не-const-ссылкой.

Смотрите, что происходит.
Компилятор пытается понять, что же ему вызывать для выражения cout << a + b
Поскольку a + b -- не lvalue, то ostream &operator<< (ostream &stream, three_d &obj) отпадает. Раз так, компилятор смотрит, как он может преобразовать аргументы, чтобы другие функции подошли.
Компилятор пробует известные ему операторы <<. Когда он пробует ostream &operator<< (ostream &stream, const int &i), он видит, что можно использовать этот оператор, если преобразовать второй аргумент в int. Поскольку вы предоставили преобразование, этот вариант проходит.

Отдельно от темы: ваш оператор сложения -- ужас! Вы модифицируете первое слагаемое!
Представьте себе, если бы сложение чисел вело себя так:
int a = 5; int b = 7; int c = a + b; // здесь внезапно a == 12
Ваш код ведёт себя именно так.
Вот как надо:
three_d three_d::operator+ (three_d op2) { return three_d(x + op2.x, y + op2.y, z + op2.z); }

Комментариев нет:

Отправить комментарий