无法分配给 const 成员函数中的非静态数据成员
Cannot assign to non-static data member within const member function
我正在尝试使用 std::unordered_set
作为散列 table 来存储许多 CreditCard
。 CreditCard
和另一个classCardDatabase
定义如下:
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
。因此,我将“const”添加到 ChangeBalance
函数中。但是,这样做之后,我在 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());
}
}
}
此外,我最初粘贴的代码来自一个更大的代码库,在发布问题之前我没有删除所有必要的命名空间内容。对于造成的混乱,我深表歉意。
ChangeBalance
具有 const 语义是不合适的。就其名称的本质而言,您正在修改对象。使函数非常量。
void ChangeBalance(int amount) {
balance += amount;
}
另一个问题是你没有正确调用你的函数。你应该这样做:
iter->ChangeBalance(chargeAmount);
我会提到在某些情况下您想要修改 const 对象中的值,并且有一个 mutable
类型修饰符。但是,不要使用它来解决您当前的错误!
void ChangeBalance(int amount)
不应该是 const
- 它正在改变对象。
问题出在迭代器之前:cards.find
returns 一个 const
对象,因此您不能更改它。
解决这个问题的方法是让您的 cards
设置一组指向卡片的指针,而不是卡片;或使用其他方式查找匹配的卡片
unordered_set
的成员是常量,一旦进入 unordered_set
,默认情况下就无法更改。您正在尝试更改集合中的对象,编译器正确地告诉您不能这样做。
正确执行此操作的唯一可能方法(仅出于教育目的进行解释,因为这是糟糕的 class 设计):
明确声明可以通过这种方式修改的各个字段为mutable
。
在您的 unordered_set
中使用自定义哈希函数,哈希函数必须从计算的哈希值中排除可变字段的值。
否则,修改集合中对象的内容,显然会改变其哈希值,这将导致未定义的行为。
再次说明,这仅供参考。这不是一个好的 class 设计。
最简单的方法是为每个 CreditCard
分配一个唯一标识符(你知道,比如信用卡号?),然后使用普通的 std::map
来查找CreditCard
他们的号码。
Hoss,在该代码中随意使用 C++ 语法。大量错误等待在拐角处
第一个错误:
iter->CreditCard::ChangeBalance(chargeAmount);
应该是
iter->ChangeBalance(chargeAmount);
由于 unordered_set
不知道如何对 CreditCard
进行散列而导致的错误,可能会导致直接错误的语法。读一读:How do I use unordered_set? That said, unordered_set
is probably not the right solution for this job. std::map<std::string, CreditCard>
看起来更准确。
使用错误的解决方案解决上述问题导致
第二个错误:
void ChangeBalance(int amount) const
方法上的 const
表示该方法不能更改对象的状态。 in ChangeBalance
balance += amount;
尝试通过更新成员变量来更改对象的状态。
此外,编译器会讨厌 CreditCard::
在这个:
CreditCard::CreditCard(string in_cardHolder, string in_cardNumber, int in_limit) {
cardHolder = in_cardHolder;
cardNumber = stoll(in_cardNumber);
limit = in_limit;
balance = 0;
}
另一种解决方案是将“余额”设为静态成员。
class CreditCard {
private:
string cardHolder;
unsigned long long cardNumber;
int limit;
static int balance;
....
}
然后在cpp文件中初始化
int CreditCard::balance = 0;
此代码可能不是很安全。但这可能是解决方法之一。
我正在尝试使用 std::unordered_set
作为散列 table 来存储许多 CreditCard
。 CreditCard
和另一个classCardDatabase
定义如下:
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
。因此,我将“const”添加到 ChangeBalance
函数中。但是,这样做之后,我在 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());
}
}
}
此外,我最初粘贴的代码来自一个更大的代码库,在发布问题之前我没有删除所有必要的命名空间内容。对于造成的混乱,我深表歉意。
ChangeBalance
具有 const 语义是不合适的。就其名称的本质而言,您正在修改对象。使函数非常量。
void ChangeBalance(int amount) {
balance += amount;
}
另一个问题是你没有正确调用你的函数。你应该这样做:
iter->ChangeBalance(chargeAmount);
我会提到在某些情况下您想要修改 const 对象中的值,并且有一个 mutable
类型修饰符。但是,不要使用它来解决您当前的错误!
void ChangeBalance(int amount)
不应该是 const
- 它正在改变对象。
问题出在迭代器之前:cards.find
returns 一个 const
对象,因此您不能更改它。
解决这个问题的方法是让您的 cards
设置一组指向卡片的指针,而不是卡片;或使用其他方式查找匹配的卡片
unordered_set
的成员是常量,一旦进入 unordered_set
,默认情况下就无法更改。您正在尝试更改集合中的对象,编译器正确地告诉您不能这样做。
正确执行此操作的唯一可能方法(仅出于教育目的进行解释,因为这是糟糕的 class 设计):
明确声明可以通过这种方式修改的各个字段为
mutable
。在您的
unordered_set
中使用自定义哈希函数,哈希函数必须从计算的哈希值中排除可变字段的值。
否则,修改集合中对象的内容,显然会改变其哈希值,这将导致未定义的行为。
再次说明,这仅供参考。这不是一个好的 class 设计。
最简单的方法是为每个 CreditCard
分配一个唯一标识符(你知道,比如信用卡号?),然后使用普通的 std::map
来查找CreditCard
他们的号码。
Hoss,在该代码中随意使用 C++ 语法。大量错误等待在拐角处
第一个错误:
iter->CreditCard::ChangeBalance(chargeAmount);
应该是
iter->ChangeBalance(chargeAmount);
由于 unordered_set
不知道如何对 CreditCard
进行散列而导致的错误,可能会导致直接错误的语法。读一读:How do I use unordered_set? That said, unordered_set
is probably not the right solution for this job. std::map<std::string, CreditCard>
看起来更准确。
使用错误的解决方案解决上述问题导致
第二个错误:
void ChangeBalance(int amount) const
方法上的 const
表示该方法不能更改对象的状态。 in ChangeBalance
balance += amount;
尝试通过更新成员变量来更改对象的状态。
此外,编译器会讨厌 CreditCard::
在这个:
CreditCard::CreditCard(string in_cardHolder, string in_cardNumber, int in_limit) {
cardHolder = in_cardHolder;
cardNumber = stoll(in_cardNumber);
limit = in_limit;
balance = 0;
}
另一种解决方案是将“余额”设为静态成员。
class CreditCard {
private:
string cardHolder;
unsigned long long cardNumber;
int limit;
static int balance;
....
}
然后在cpp文件中初始化
int CreditCard::balance = 0;
此代码可能不是很安全。但这可能是解决方法之一。