【问题标题】:Cannot assign to non-static data member within const member function无法分配给 const 成员函数中的非静态数据成员
【发布时间】:2016-10-06 01:58:27
【问题描述】:

我正在尝试使用std::unordered_set 作为哈希表来存储许多CreditCardCreditCard 和另一个类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());
        }
    }
}

另外,我最初粘贴的代码来自一个更大的代码库,在发布问题之前我没有删除所有必要的命名空间内容。对于造成的混乱,我深表歉意。

【问题讨论】:

  • 您希望CreditCard::CreditCardCreditCard::ChangeBalance 做什么?

标签: c++ c++11 unordered-set


【解决方案1】:

默认情况下,unordered_set 的成员是不变的,一旦进入 unordered_set,就无法更改。您正在尝试更改集合中的对象,编译器正确地告诉您不能这样做。

正确执行此操作的唯一可能方法(仅出于教育目的进行解释,因为这是糟糕的类设计):

  1. 将可以以这种方式修改的各个字段显式声明为mutable

  2. 对您的unordered_set 使用自定义哈希函数,并且哈希函数必须从计算的哈希值中排除可变字段的值。

否则,修改集合中对象的内容显然会改变其哈希值,从而导致未定义的行为。

再次说明,这仅供参考。这不是一个好的类设计。

执行此操作的简洁方法是为每个 CreditCard 分配一个唯一标识符(您知道,就像信用卡号一样?),并使用普通的 std::map,通过他们的 CreditCards 查找号码。

【讨论】:

  • 感谢您的回答和有用的解释
【解决方案2】:

ChangeBalance 不适合具有 const 语义。就其名称的本质而言,您正在修改对象。使函数非常量。

void ChangeBalance(int amount) {
    balance += amount;
}

另一个问题是你没有正确调用你的函数。你应该这样做:

iter->ChangeBalance(chargeAmount);

我会提到在某些情况下您想要修改 const 对象中的值,并且有一个 mutable 类型修饰符。但是,不要用它来解决你当前的错误!

【讨论】:

  • 感谢您如此迅速地回复。 CreditCard:: 的原因是因为我只从更大的代码库中复制出现错误的部分。我已经相应地编辑了我的问题
  • iter-&gt;CreditCard::ChangeBalance(chargeAmount); 是正确的,CreditCard:: 在这种情况下是多余的(但您可能希望在其他类层次结构中包含它)。
【解决方案3】:

void ChangeBalance(int amount) 不应该是 const - 它正在更改对象。

问题出在之前的迭代器中:cards.find 返回一个const 对象,所以不允许修改。

解决这个问题的方法是让您的cards 设置一组指向卡片的指针,而不是卡片;或使用其他方式查找匹配卡

【讨论】:

    【解决方案4】:

    Hoss 在那段代码中快速而松散地使用 C++ 语法。大量错误在拐角处等待

    第一个错误:

    iter->CreditCard::ChangeBalance(chargeAmount);
    

    应该是

    iter->ChangeBalance(chargeAmount);
    

    由于unordered_set 不知道如何散列CreditCard 导致的错误,可能会导致乱七八糟的错误语法。读一读:How do I use unordered_set? 也就是说,unordered_set 可能不是这项工作的正确解决方案。 std::map&lt;std::string, CreditCard&gt; 看起来更重要。

    使用错误的解决方案来解决上述问题会导致

    第二个错误:

    void ChangeBalance(int amount) const
    

    const 在方法上意味着该方法不能改变对象的状态。在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;
    }
    

    【讨论】:

      【解决方案5】:

      另一种解决方案是将“平衡”设为静态成员。

          class CreditCard {
      private:
          string cardHolder;
          unsigned long long cardNumber;
          int limit;
          static int balance;
          ....
         }
      

      然后在cpp文件中初始化

      int CreditCard::balance = 0;
      

      此代码可能不是很安全。但这可能是解决方法之一。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-03
        • 2018-09-18
        • 1970-01-01
        • 2017-10-11
        • 1970-01-01
        相关资源
        最近更新 更多