Перегруженный оператор присваивания вызывает предупреждение о рекурсии - PullRequest
2 голосов
/ 26 декабря 2011

Мне нужно реализовать перегруженный оператор присваивания в классе, чтобы функция vector.erase работала правильно, как было предложено в ответах на " vector :: erase with член-указатель ".Я реализовал также конструктор копирования для той же цели.При следующей реализации оператора я получаю предупреждение:

'Player :: operator =': рекурсивно для всех путей управления, функция вызовет переполнение стека во время выполнения.

Очевидно, реализация Player::operator= неверна.Какова правильная реализация?

//Copy constructor:
Player::Player(const Player& otherPlayer) {
   ...
}


Player& Player::operator=(const Player& rhs) {
    *this = Player(rhs);
    return *this;
}

Работает ли функция стирания мультикарты так же, как вектор?Когда я использую мультикарту, я не получаю ошибок о том, что не реализован перегруженный operator=, как это происходит с вектором.Что является правдой?

Кроме того, у игрока есть ссылка на банк как члена.Должен ли я сделать присвоение ссылки только через =?Какова же цель конструктора копирования?

Ответы [ 4 ]

7 голосов
/ 26 декабря 2011

Ваша проблема в этой строке:

*this = Player(rhs);

Это снова вызывает перегруженный метод =, что приводит к рекурсивному циклу.Вы должны назначить все члены по отдельности:

x = rhs.x;
y = rhs.y; // for example

EDIT Также обратите внимание, что поскольку объект, который вы передаете, относится к тому же типу объекта, к которому принадлежит метод экземпляра, вы можете получить доступ к закрытым членамкак обычно для публичных членов.

EDIT2 Насколько я знаю, вы бы не хотели бы копировать ссылку, потому что это означает, что тот же объект Bank будетбыть доступным из обоих объектов, что нарушает инкапсуляцию и может вызвать некоторые непреднамеренные проблемы.Есть ли какая-то конкретная причина, по которой вы не используете указатели?Если бы объект банка был указателем, вы могли бы перегрузить оператор = для банка, а затем назначить его обычным образом:

bank = rhs.bank;

Что касается разницы конструкторов копирования и операторов назначения, то появился быстрый поиск в Googleэта ссылка: http://prashanth -cpp.blogspot.com / 2007/01 / assignment-operator-vs-copy-constructor.html

4 голосов
/ 26 декабря 2011

Хороший способ правильно реализовать operator= - это идиома копирования и обмена :

Player& Player::operator=(Player rhs) {  // note: pass by value
  this->swap(rhs);
  return *this;
}

void Player::swap(Player& other) {  // member function
  using std::swap;
  swap(this->name, other.name);
  swap(this->score, other.score);
}

void swap(Player& a, Player& b) {  // free function
  a.swap(b);
}
1 голос
/ 26 декабря 2011

Проблема в том, что вы звоните = изнутри =.Вместо этого вам следует присваивать элементы вашего поля класса по полю, например:

Player& Player::operator=(const Player& rhs) {
    name = rhs.name;
    score = rhs.score;
    return *this;
}
0 голосов
/ 26 декабря 2011

В ответ на

Какова цель конструктора копирования?

Цель - дать вам самый полный контроль над тем, что делает копирование.
Например, если ваш класс содержит char* член, и вы делаете копию, вы можете оставить для char * то же значение, что и в экземпляре, который вы копируете (т. Е. Указатель, указывающий нато же самое местоположение оригинала), или вы можете создать копию строки, на которую он указывает.
Компилятор не знает сам по себе, какой из этих вариантов вы хотите, так что вы попадаете туда.

...