C++使用greater报错‘this‘ argument has type ‘const xxx‘, but method is not marked const的解决方案
使用STL的时候难免遇到需要自己定义排序函数的时候,这时候greater和less就能起到很大作用。但之前排序的对象都是基本类型(或者基本类型的容器),这次要给自定义类型排序,就遇到了问题。比如,我有这么一个场景,我想要给二维空间里的点做一个优先队列,从大到小排个序;所以我先定义一个Point类。因为需要进行大于的比较,所以我重载一个>运算符:class Point{int val, x,
使用STL的时候难免遇到需要自己定义排序函数的时候,这时候greater
和less
就能起到很大作用。但之前排序的对象都是基本类型(或者基本类型的容器),这次要给自定义类型排序,就遇到了问题。
比如,我有这么一个场景,我想要给二维空间里的点做一个优先队列,从大到小排个序;所以我先定义一个Point
类。因为需要进行大于的比较,所以我重载一个>
运算符:
class Point
{
int val, x, y;
Point(int val, int x, int y) : val(val), x(x), y(y) {}
bool operator>(const Point &p) const { return val > p.val; }
};
然后再定义一个优先队列(用STL的优先队列):
priority_queue<Point, vector<Point>, greater<Point>> q;
到这里都没什么问题。然后我插入一个坐标为(1, 1),值为1的点:
q.emplace(1, 1, 1);
然后就报错了。
找了半天也不知道为啥,后来查了一下greater
的文档,看到里面是这么写的:
std::greater::operator()
bool operator()( const T& lhs, const T& rhs ) const; (until C++14) constexpr bool operator()( const T& lhs, const T& rhs ) const; (since C++14) Checks whether
lhs
is greater thanrhs
.
然后我意识到,greater的内部实现是一个const的成员函数,也就是常成员函数。而我们知道,常成员函数是不能调用普通的成员函数的。原因很简单,因为常成员函数是保证不会修改成员变量的,而普通成员函数不保证是否会修改成员变量,如果常成员函数调用了普通成员函数,就有可能会出现声明和实际行为不一致的情况(声明保证不会修改,却偷偷把值给改了),这种情况是不允许出现的,所以就报错了。
解决办法也很简单,加个const,声明为常成员函数就行了:
class Point
{
int val, x, y;
Point(int val, int x, int y) : val(val), x(x), y(y) {}
bool operator>(const Point &p) const { return val > p.val; }
};
另外,参数里的const也是不能少的。为啥呢,理由还是和刚才一样,greater在调用的时候传入的lhs和rhs都是常量,如果我重载的运算符的参数为非常量,相当于把常量赋值给非常量,显然是不行的。
更多推荐
所有评论(0)