C ++ set方法:函数'setCost'不可行:'this'参数的类型为'const value_type'

时间:2017-01-29 19:19:47

标签: c++

我无法通过set方法将值设置为私有成员变量。得到错误

member function 'setCost' not viable: 'this' argument has type 'const value_type' (aka 'const Position'), but function is not marked const

我的代码如下:

class Position {
public:
    Position();
    Position(int x, int y);
    int getCost() const;
    void setCost (int c);
private:
    int x;
    int y;
    int cost;
    };


void Position::setCost (int c){
    this->cost = c;
}

class Board{
public:
    Board();
    Board(int N);
    void shortestPath32 (Position start, Position end);
private:
    int N;
    char W[32][32];
};

void Board::shortestPath32 (Position start, Position end){

  /* some code here */

    set <Position> validMoves = getValidPositions(parent);
    for(auto child =validMoves.begin(); child!=validMoves.end(); ++child ){
        /*some code here ...*/  
        int c = 5
        (*child).setCost(c);

        }

    }
}

显然,如果我将setCost声明为void Position::setCost (int c) const,我无法在内部执行赋值操作。另外,我查看了this thread的set方法,但没有帮助。

3 个答案:

答案 0 :(得分:2)

这是std::set的限制 - 它的迭代器总是返回const引用。理由是 - 修改集合中的元素可以改变其位置,因此不允许这样做。

要修改集合中的元素,官方流程是将其从集合中删除,修改并重新插入。

现在,如果您知道修改某些元素属性不会影响其位置,那么作为一种肮脏的解决方法,您可以声明那些mutable和setter const

class Position {
public:
    Position();
    Position(int x, int y);
    int getCost() const;
    void setCost (int c) const { cost = c; }
private:
    int x;
    int y;
    mutable int cost;
};

一个更脏的解决方案是抛弃const,然后你可以修改任何东西(我觉得很脏,甚至提起它)。

P.S。通过选择更符合您需求的结构,通常可以避免这个问题 - 例如std::map;您可以将代码重构为PositionCost

class Position {
    int x;
    int y;
    . . .
};
class Cost {
    int cost;
    . . .
};

std::map<Position,Cost> validMoves;

然后,您将能够合法地修改Cost,而Position可以保留const

  for(auto it =validMoves.begin(); it!=validMoves.end(); ++it){
      it->second.setCost(c);
  }

但这是一个设计选择,可能取决于问题中未提及的其他因素......

答案 1 :(得分:1)

根据文件, 集合中元素的值不能在容器中修改一次(元素总是const),但可以在容器中插入或删除它们。

所以你需要在集合中擦除并重新插入。

How to update an existing element of std::set?

答案 2 :(得分:0)

正如其他人所提到的,你可以抛弃const,但这不是最好的解决方案,如果你这样做,你必须确保成本没有被使用。您可以使用map替换set并将成本存储在类之外。

然后您可以执行以下操作......

void Board::shortestPath32 (Position start, Position end){
  map<Position, int> validMoves; //getValidPositions(parent);    
  for(auto child=validMoves.begin(); child!=validMoves.end(); ++child ){  
    child->second=1; // NYI - replace 1 with the cost    
  }  
}