C++ C++;设置方法:函数';设置成本';不可行:';这';参数的类型为';常量值类型';

C++ C++;设置方法:函数';设置成本';不可行:';这';参数的类型为';常量值类型';,c++,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); in

我无法通过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);

        }

    }
}
类位置{
公众:
位置();
位置(整数x,整数y);
int getCost()常量;
无效设置成本(INTC);
私人:
int x;
int-y;
国际成本;
};
无效位置::设置成本(int c){
这个->成本=c;
}
班级委员会{
公众:
董事会();
董事会(int N);
void shortestPath32(位置开始,位置结束);
私人:
int N;
字符W[32][32];
};
无效板::最短路径32(位置开始,位置结束){
/*这里有一些代码*/
设置validMoves=getValidPositions(父级);
for(自动子项=有效移动.begin();子项!=有效移动.end();++child){
/*这里有一些代码…*/
int c=5
(*儿童)。设定成本(c);
}
}
}
显然,如果我将setCost声明为
void Position::setCost(int c)const
,我就无法在内部执行赋值操作。此外,我还研究了set方法,但没有任何帮助。

根据文档, 集合中元素的值在容器中不能修改一次(元素始终为常量),但可以从容器中插入或删除它们

因此,您需要在集合中擦除并重新插入

根据文件, 集合中元素的值在容器中不能修改一次(元素始终为常量),但可以从容器中插入或删除它们

因此,您需要在集合中擦除并重新插入


这是
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;
};
class Position {
    int x;
    int y;
    . . .
};
class Cost {
    int cost;
    . . .
};

std::map<Position,Cost> validMoves;
  for(auto it =validMoves.begin(); it!=validMoves.end(); ++it){
      it->second.setCost(c);
  }
一个更肮脏的解决方案是扔掉
const
,然后你可以修改任何东西(即使提起这个我也觉得肮脏)

另外,通常可以通过选择更适合您需要的结构来避免这个问题,例如
std::map
;您可以将代码重构为
位置
成本

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;
};
class Position {
    int x;
    int y;
    . . .
};
class Cost {
    int cost;
    . . .
};

std::map<Position,Cost> validMoves;
  for(auto it =validMoves.begin(); it!=validMoves.end(); ++it){
      it->second.setCost(c);
  }

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

这是
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;
};
class Position {
    int x;
    int y;
    . . .
};
class Cost {
    int cost;
    . . .
};

std::map<Position,Cost> validMoves;
  for(auto it =validMoves.begin(); it!=validMoves.end(); ++it){
      it->second.setCost(c);
  }
一个更肮脏的解决方案是扔掉
const
,然后你可以修改任何东西(即使提起这个我也觉得肮脏)

另外,通常可以通过选择更适合您需要的结构来避免这个问题,例如
std::map
;您可以将代码重构为
位置
成本

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;
};
class Position {
    int x;
    int y;
    . . .
};
class Cost {
    int cost;
    . . .
};

std::map<Position,Cost> validMoves;
  for(auto it =validMoves.begin(); it!=validMoves.end(); ++it){
      it->second.setCost(c);
  }

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

正如其他人所提到的,您可以放弃常量,但这不是最佳解决方案,如果您这样做,您必须确保排序中不使用成本。您可以用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    
  }  
}
void Board::最短路径32(位置开始,位置结束){
map validMoves;//getValidPositions(父级);
对于(auto-child=validMoves.begin();child!=validMoves.end();++child){
child->second=1;//NYI-将1替换为成本
}  
}

正如其他人所提到的,您可以放弃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    
  }  
}
void Board::最短路径32(位置开始,位置结束){
map validMoves;//getValidPositions(父级);
对于(auto-child=validMoves.begin();child!=validMoves.end();++child){
child->second=1;//NYI-将1替换为成本
}  
}

您正在尝试对集合的元素进行变异。集合不允许这样做,因为这会破坏集合的内部组织,并可能违反元素的唯一性。无论如何,为什么成本是职位的一部分?最好有一张从位置到成本的地图。你正在尝试改变集合的元素。集合不允许这样做,因为这会破坏集合的内部组织,并可能违反元素的唯一性。无论如何,为什么成本是职位的一部分?最好有一个从头寸到成本的映射图。只是要明确一点:直接修改
集合
映射
(或任何其他类似容器)中的数据可能会导致数据损坏。更准确地说,修改键中影响
集合
映射
中元素位置的部分将导致数据损坏,而修改任何其他部分都不会导致数据损坏。关键部分是
操作符“
begin()
end()
始终返回
const
迭代器”使用的字段,这一措辞有点草率。它们不返回
常量迭代器
,也不返回
常量迭代器
const
ov