lvalue требуется в качестве левого операнда присваивания для перегрузки оператора

Я пытаюсь выполнить перегрузку оператора, но продолжаю получать сообщение об ошибке, когда запускаю этот код из .cpp.

Прототип заголовочного файла выглядит следующим образом:

const Velocity & operator = (const Velocity & rhs);

И функция-член .cpp выглядит так.

const Velocity & Velocity :: operator = (const Velocity & rhs)
{
   this->getDx() = rhs.getDx();
   this->getDy() = rhs.getDy();
   this->getX() = rhs.getX();
   this->getX() = rhs.getY();
   return *this;
}

где в основном выглядит использование оператора.

Velocity v1;
Velocity v2;
Velocity v3;

promptVelocity("Enter values for Velocity 1", v1);
promptVelocity("Enter values for Velocity 2", v2);

// Test operator =
v3 = v1;
cout << "Test operator = : " << v3 << endl;

Я получаю сообщение об ошибке для строк this->

lvalue required as left operand of assignment

Пожалуйста помоги!


person w33b    schedule 19.02.2015    source источник
comment
Назначаемый геттер... странный и, вероятно, неправильный. Не кажется ли вам, что вы должны показать нам их декларации? Кроме того, оператор присваивания, возвращающий ссылку на константу, является странным... вы пытаетесь защититься от чего-то вроде (x=y)=z? Кажется ненужным.   -  person Ed S.    schedule 19.02.2015
comment
Прежде всего - мы угадываем вашу реализацию геттеров. Во-вторых, вы должны создать минимальный рабочий пример вашей проблемы. В-третьих, почему вы думаете, что использование метода геттера для установки значения является хорошей идеей?   -  person zoska    schedule 20.02.2015


Ответы (2)


Измените свою функцию на:

Velocity& Velocity::operator=(const Velocity& rhs) {
  dx_ = rhs.getDx();
  dy_  = rhs.getDy();
  x_ = rhs.getX();
  y_ = rhs.getY();
  return *this;
}

... предполагая, что "dx_", "dy_" и т. д. - это имена реальных переменных. Левая часть присваивания должна быть "lvalue" (чтобы определить ее просто - именованная переменная с адресом), тогда как до того, как вы использовали "rvalue" (временная переменная, которая была возвращена в результате соответствующие функции «получить»). Чтобы разобраться в этом немного подробнее, скорее всего, ваши различные функции «получить» возвращают объект типа значения (например, «int») или константную ссылку (например, «const int&»), но чтобы присвоить что-то, вы действительно нужна изменяемая ссылка (например, "int&"). Присвоение выходных данных функции "get", которая возвращает простой тип значения, бессмысленно, потому что функция get создает копию базовых данных перед ее возвратом. Хотя эта копия может иметь связанный с ней адрес памяти (например, если она была сохранена в стеке, например), присвоение ей не дало бы наблюдаемого эффекта, потому что эта копия ничего не делает и нигде не видна, если она не назначена к некоторой переменной. Однако когда вы используете имя переменной-члена в левой части, назначение на самом деле имеет смысл, поскольку на переменную, получающую присвоение, все еще можно ссылаться в другом месте.

Я также должен отметить, что в своем изменении я удалил кучу лишних this->es. Есть только два случая, когда this-> строго необходим:

  1. Существует символ с тем же именем, который «закрывает» элемент this (например, параметр или другая локальная переменная с более узкой областью действия, чем область действия класса), и в этом случае необходимо использовать this-> для выбора члена вместо местный.

  2. Очень неточно: используется template, так что необходимо явно использовать this->, чтобы заставить C++ искать в этом классе, а не в области пространства имен (см. поиск зависимого имени для более точного объяснения).

В отсутствие этих двух случаев поиск символов правильно найдет переменные-члены без this-> и, следовательно, он избыточен и, следовательно, его следует избегать (на мой взгляд).

Кроме того, я изменил возвращаемый тип присваивания с "const Velocity&" на "Velocity&", поскольку операторы присваивания обычно возвращают изменяемый экземпляр присваиваемого объекта, и поступать иначе было бы неожиданно; например, заставить функцию возвращать константу breaks:

Velocity velocity = // ...
Velocity default_vaue = // ...
// ... many lines later ...
if (/* some condition /*) {
  ReassignIfInvalid(velocity = ComputeSomething(), default_value);
}

... где функция «ReassignIfInvalid» требует, чтобы параметр был изменяемым, чтобы он мог условно перезаписывать значение. Хотя приведенный выше код может быть не лучшим кодом для подражания, тем не менее, он удивит, если результат присваивания неизменен.

person Michael Aaron Safyan    schedule 19.02.2015
comment
Цепное присваивание работает правильно независимо от того, является ли возвращаемая ссылка константной. Есть веские причины для возврата неконстантной ссылки, но заставить работать x = y = z — не одна из них. - person T.C.; 19.02.2015
comment
@Т.С. Я забыл добавить свои скобки. Несмотря на это, общая точка зрения, что это необходимо для цепочек вызовов изменяемых операций, остается в силе. - person Michael Aaron Safyan; 19.02.2015
comment
Нас действительно волнует дело (x=y)=z? Кто пишет этот код? - person Ed S.; 19.02.2015
comment
@MichaelAaronSafyan У меня есть доступ к переменным dx и dy, но переменные x и y являются частными. Чтобы назначить их, мне нужно будет использовать для них мою функцию получения? - person w33b; 19.02.2015
comment
@ Эд, в этом случае, вероятно, нет, но если (Process (x = y)) где Process принимает изменяемый объект, это может вас волновать. Очень удивительно/нестандартно, когда присваивание возвращает константу. - person Michael Aaron Safyan; 19.02.2015
comment
@gman54 gman54, нет, вам не нужно использовать функции получения ... класс может получить доступ к своим собственным закрытым переменным. - person Michael Aaron Safyan; 20.02.2015

В функции .cpp вы говорите, что функция-получатель должна получить значение из другой функции, поэтому на самом деле вы ничего не делаете. Если он у вас есть, используйте функцию установки. Хотя вам лучше сделать свои значения общедоступными, а не использовать геттеры и сеттеры.

person Community    schedule 19.02.2015
comment
Я бы сделал переменную общедоступной, но присваивание требует приватных переменных - person w33b; 19.02.2015
comment
не делайте переменную общедоступной, используйте методы установки - person zoska; 20.02.2015
comment
но с использованием методов получения и установки это почти как общедоступная переменная, не так ли? - person ; 23.02.2015