我有以下代码:
class Test{
private:
int id;
public:
Test(int v):id(v) {}
int getId() { return id;}; // however,I change this method signature
int getId() const { return id;};
and all the errors gone
};
struct compare{
bool operator()(const Test& t1, const Test& t2){
return t1.getId() < t2.getId(); // got error here
}
};
int main(int argc, char *argv[]){
set<Test, compare> s;
Test str[] = {Test(1), Test(2), Test(3)};
for (int i = 0; i < 3; ++i){
s.insert(str[i]);
}
for (set<Test>::iterator it = s.begin(); it != s.end(); ++it){
cout << it->getId() << "\n"; // got error here
}
return EXIT_SUCCESS;
}
当我使用该代码调用方法getId()时出现此错误:
passing `const Test' as `this' argument of `int Test::getId()' discards qualifiers
我不知道为什么我需要在方法getId()中使用 const 来修复该错误?感谢
答案 0 :(得分:10)
bool operator()(const Test& t1, const Test& t2)
您的操作员会引用const Test
个对象。您只能通过引用const
- 限定类型来调用const
- 合格的成员函数。
set<Test>::iterator it = s.begin()
std::set
的元素是不可变的:你无法改变它们。因此,std::set
中的迭代器始终为const
- 限定类型的对象。
答案 1 :(得分:3)
set::iterator
只允许const
访问元素,因为更改可能会影响集合元素的相对顺序 - 它需要保护的不变量(即如果更改集合中的元素,则为可能会破坏集合中元素的假定排序,并且将来的查找,插入等将无法按预期可靠地工作)。因此,只能通过const
对元素访问调用iterator
个成员函数。
这有点令人困惑,因为对于其他一些容器,const_iterator
vs iterator
的选择决定了授予的访问权限。
答案 2 :(得分:2)
const Test& t1
使t1
保持不变,也就是说,不能通过此引用更改它。现在,您在该对象上调用的任何函数都可以更改其内部状态 - const
不允许这样做!
这是怎么解决的?只需标记不会将内部状态更改为const
的函数!这意味着,可以在const对象/引用/指针上调用它们
这就是为什么在const
函数之后需要getId
的原因,以确保您不会更改任何内部状态。
int getId() const { return id;};
修改:当然,这同样适用于std::set
,但我不会进入其中,因为其他答案已经这样做了。
答案 3 :(得分:1)
您只能在const对象上调用const成员函数。
set<Test>::iterator it = s.begin();
返回一个const对象,所以你只调用带有这个对象的const类型的调用成员函数。
答案 4 :(得分:0)
operator()在其参数列表中有const Test&
个对象,所以当你通过const对象调用时,你的函数需要用const限定符声明。
int getId() const { return id;};
同样改变,
for (std::set<Test, compare>::const_iterator it = s.begin(); it != s.end(); ++it){
std::cout << it->getId() << "\n"; // got error here
}