我正在尝试使用 std::unordered_set
作为哈希表来存储许多 CreditCard
的。 CreditCard
和另一个类 CardDatabase
定义如下:
class CreditCard {
private:
string cardHolder;
unsigned long long cardNumber;
int limit;
int balance;
public:
CreditCard(string in_cardHolder, string in_cardNumber, int in_limit) {
cardHolder = in_cardHolder;
cardNumber = stoll(in_cardNumber);
limit = in_limit;
balance = 0;
}
void ChangeBalance(int amount) const {
balance += amount; // SECOND ERROR
}
};
class CardDatabase {
private:
unordered_set<CreditCard> cards;
unordered_set<CreditCard>::iterator iter;
public:
CardDatabase() { }
void AddCard(cardHolder, cardNumber, int limit) {
CreditCard tempCard = CreditCard(cardHolder, cardNumber, limit);
cards.insert(tempCard);
}
void Charge(string cardHolder, int chargeAmount) {
iter = cards.find(cardHolder);
iter->ChangeBalance(chargeAmount); // FIRST ERROR
}
}
最初我在 FIRST ERROR
得到以下编译错误: Member function 'ChangeBalance' not viable: 'this' argument has type 'const CreditCard', but function is not marked const
。所以,我在 ChangeBalance
函数中添加了“const”。但是,在这样做之后,我在 SECOND ERROR
得到以下编译错误: Cannot assign to non-static member within const member function 'ChangeBalance'
。
有没有办法在不将 balance
更改为静态变量的情况下修复此错误?显然,每个 CreditCard
实例的余额不同是很重要的。
任何帮助表示赞赏。
编辑:
谢谢大家的快速回答。我觉得我应该澄清一些事情。我已经在代码的其他地方添加了适当的哈希功能:
namespace std {
template <>
struct hash<CreditCard> {
size_t operator()(const CreditCard& cc) const
{
return hash<string>()(cc.GetCardHolder());
}
}
}
此外,我最初粘贴的代码来自一个更大的代码库,在发布问题之前我没有删除所有必要的命名空间内容。我为混乱道歉。
原文由 bpgeck 发布,翻译遵循 CC BY-SA 4.0 许可协议
unordered_set
的成员是常量,默认情况下,一旦它们在unordered_set
中就不能更改。您正在尝试更改集合中的对象,编译器正确地告诉您您不能这样做。正确执行此操作的唯一可能方法(仅出于教育目的进行解释,因为这是糟糕的班级设计):
将可以以这种方式修改的各个字段显式声明为
mutable
。对您的
unordered_set
使用自定义哈希函数,并且哈希函数必须从计算的哈希值中排除可变字段的值。否则,修改集合中对象的内容显然会改变其哈希值,从而导致未定义的行为。
同样,这仅出于提供信息的目的进行解释。这不是一个好的类设计。
干净的方法是为每个
CreditCard
分配一个唯一标识符(你知道,就像信用卡号一样?),并使用普通的std::map
来查找CreditCard
按他们的编号。