Страницы

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

суббота, 4 января 2020 г.

Перегрузка оператор присвоения

#cpp



Изучаю язык. Написал простенький класс:

class Point{
public:
  Point();
  Point(int x, int y);      
private:
  int _x;
  int _y;
}


Захотел преобразовать его в другой тип. По не знанию и паскалевской привычки
написал такой оператор:

int operator=(const Point& src);


Скомпилировал класс вместе с оператором и все нормально скомпилировалось.
Решил проверить на коде:

int main(int argc, char *argv[])
{
  Point pt(1, 2);    
  int i;
  i = pt;
}


Компиляция не удалась:   

main.cpp:14: ошибка: cannot convert 'Point' to 'int' in assignment


Потом я нашел как преобразовать тип через другой оператор. Но мне интересно, раз
компилятор дал мне скомпилировать этот оператор, значит наверно его, как то можно применить. 

Вопрос: Что это оператор делает и как его можно использовать?
    


Ответы

Ответ 1



Надо различать оператор присвоения и функцию преобразования. Оператор присвоения не меняет тип объекта, которому присваивается выражение. В вашем примере class Point{ public: //... int operator=(const Point& src); //... }; оператор присваивания присваивает выражение объекту класса Point. Причем присваиваемое выражение имеет также ссылочный тип класса Point. Вы можете использовать возвращаемое значение выражения с данным оператором присваивания, чтобы присвоить его переменной типа int. Например, int main(int argc, char *argv[]) { Point pt(1, 2); int i; i = pt = pt; } Так как операторы присваивания выполняются справа налево, то сначала бы выполнилось присваивание pt = pt результатом которого было бы значение типа int, и только во втором присваивании это значение было бы занесено в переменную i Если же вы хотите написать оператор преобразования, то он может выглядеть следующим образом: operator int() const; И тогда вы можете записать i = pt; Имейте в виду, что для не пользовательских типов вы не можете переопределить оператор присваивания. И в этом предложении i = pt; используется стандартное присваивание для целых чисел. Но так как pt не имеет целочисленный тип, то компилятор пытается его преобразовать к объекту целочисленного типа и вызывает для pt оператор operator int() const; если вы его определили. Иначе компилятор выдаст сообщение об ошибке.

Ответ 2



Когда вы пишете a = b, это транслируется как a.operator=(b). То есть, для вашего случая (i = pt) вам нужно бы перегрузить оператор присваивания у i, в типе данных int. Это, очевидно, невозможно. Правильный путь — оператор преобразования типов operator int() const. Заметьте, что другие, сложные операторы присваивания вполне можно перегрузить и вне класса-получателя. Например, operator += (пример): class Point { public: Point() : _x(), _y() {} Point(int x, int y) : _x(x), _y(y) {} friend int& operator += (int& i, const Point& pt) { i += pt._x; i += pt._y; return i; } private: int _x; int _y; };

Ответ 3



Интересно то, что никто так и не показал как реализовать оператор присваивания... class Point { public: Point(); Point( int x, int y ); Point & operator = ( const Point & rhs ) { if ( &rhs != this ) { _x = rhs._x; _y = rhs._y; } return *this; } private: int _x; int _y; };

Ответ 4



Выше все ответили правильно. Забавно, что если использовать Ваше описание класса Point, то можно написать следующее: Point x(1, 2); Point y(3, 4); int i = y = x; И в i останется то, что Вы хотели получить. class A { public: A(int v) {this->v = v;} A(const A &a) { v = a.v; } int operator= (const A &a) { this->v = a.v; return v; } private: int v; }; int main(int argc, char *argv[]) { A x(1); A y(2); int i = y = x; cout << i; } выводит как раз 1

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

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