无法在const成员函数内分配给非静态数据成员

时间:2016-10-06 01:58:27

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

我正在尝试使用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 ERRORMember function 'ChangeBalance' not viable: 'this' argument has type 'const CreditCard', but function is not marked const收到以下编译错误。所以,我将“const”添加到ChangeBalance函数中。但是,在执行此操作后,我在SECOND ERRORCannot 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());
        }
    }
}

另外,我最初粘贴的代码来自更大的代码库,在发布问题之前我没有删除所有必要的命名空间。我为这种困惑道歉。

4 个答案:

答案 0 :(得分:4)

unordered_set的成员是固定的,默认情况下,一旦他们在unordered_set中就无法更改。您正在尝试更改集合中的对象,编译器正在告诉您不能执行此操作。

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

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

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

  3. 否则,修改集合中对象的内容会明显改变其哈希值,这将导致未定义的行为。

    同样,这仅用于提供信息。这不是一个好的课堂设计。

    执行此操作的干净方法是为每个CreditCard分配一个唯一标识符(您知道,就像信用卡号码?),并使用普通std::map查找{{ 1}} s的数量。

答案 1 :(得分:2)

ChangeBalance不适合 const 语义。根据它名称的本质,你正在修改对象。使函数非常量。

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

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

iter->ChangeBalance(chargeAmount);

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

答案 2 :(得分:1)

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

问题出现在迭代器中:cards.find返回一个const对象,因此不允许更改它。

解决这个问题的一种方法是让你的cards设置一组指向卡片的指针,而不是卡片;或者用另一种方法找到匹配的卡

答案 3 :(得分:0)

在该代码中使用C ++语法快速松散,Hoss。很多错误都在拐角处等待

第一个错误:

iter->CreditCard::ChangeBalance(chargeAmount);

应该是

iter->ChangeBalance(chargeAmount);

由于unordered_set不知道如何散列CreditCard导致的错误,可能导致错误的语法错误。读一下:How do I use unordered_set?那就是说,unordered_set可能不是这项工作的正确解决方案。 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;
}