C++使用greater報錯‘this‘ argument has type ‘const xxx‘, but method is not marked const的解決方案

使用STL的時候難免遇到需要自己定義排序函數的時候,這時候greaterless就能起到很大作用。但之前排序的對象都是基本類型(或者基本類型的容器),這次要給自定義類型排序,就遇到了問題。

比如,我有這麼一個場景,我想要給二維空間裏的點做一個優先隊列,從大到小排個序;所以我先定義一個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 than rhs.

然後我意識到,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都是常量,如果我重載的運算符的參數爲非常量,相當於把常量賦值給非常量,顯然是不行的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章