Как использовать метод одного объекта для обновления атрибута другого объекта?
Вопрос
У меня есть три класса (С++):Игрок, рука и карта.
У игрока есть член, рука, которая держит руку.У него также есть метод getHand(), который возвращает содержимое руки.
Hand Player::getHand() {
return hand;
}
У Hand есть метод addCard(Card c), который добавляет карту в руку.
Я хочу сделать это:
player1.getHand().addCard(c);
но это не работает.Ошибок не выдает, значит что-то делает.Но если я позже проверю содержимое руки игрока 1, карта не будет добавлена.
Как я могу заставить это работать?
Решение
Если getHand() не возвращает ссылку, у вас будут проблемы.
Другие советы
Если getHand() возвращает по значению, вы изменяете копию руки, а не оригинал.
Метод Player.addCardToHand() не является необоснованным, если у вас нет причин иным образом раскрывать руку.Вероятно, в некотором смысле это идеально, так как вы все равно можете предоставить копии Руки для сравнения на предмет выигрыша, и никто не сможет их изменить.
Ваш метод должен возвращать указатель или ссылку на объект Hand игрока.Затем вы можете назвать это как «player1.getHand()->addCard(c)».Обратите внимание, что это синтаксис, который вы бы использовали, если бы он был указателем.
Верните ссылку на объект руки, например.
Hand &Player::getHand() {
return hand;
}
Теперь ваша функция addCard() работает с правильным объектом.
Что такое объявление getHand()?Возвращает ли он новое значение Hand или ссылку Hand&?
Как уже было сказано, вы, вероятно, изменяете копию вместо оригинала.
Чтобы предотвратить ошибки такого рода, вы можете явно объявить конструкторы копирования и операторы равенства как частные.
private:
Hand(const Hand& rhs);
Hand& operator=(const Hand& rhs);
getX() часто является именем функции доступа к элементу x, аналогично вашему собственному использованию.Однако метод доступа «getX» также очень часто является функцией, доступной только для чтения, поэтому в других ситуациях вашей кодовой базы может быть неожиданно увидеть вызов «getX», который изменяет X.
Поэтому я бы предложил вместо того, чтобы просто использовать ссылку в качестве возвращаемого значения, немного изменить дизайн кода.Некоторые альтернативы:
- Разоблачить getMutableHand метод, который возвращает указатель (или ссылку).Возвращая указатель, вы настоятельно рекомендуете вызывающей стороне использовать обозначение указателя, чтобы любой, кто читает код, видел, что эта переменная меняет значения и не доступна только для чтения.
- Делать Игрок — подкласс Hand, так что все, что манипулирует рукой, также работает непосредственно с игроком.Интуитивно вы могли бы сказать, что Игрок — это не Рука, но функционально они имеют правильное отношение — у каждого Игрока есть ровно одна рука, и кажется, что вы действительно хотите иметь такой же доступ к Руке через Игрока, как и вы. бы напрямую.
- Непосредственно реализовать добавитькарту метод для вашего класса Player.