2011-05-18 125 views
3

我有下面這段代碼:
const成員函數

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 

我不知道爲什麼我需要const getId()方法來修復該錯誤?謝謝

回答

10
bool operator()(const Test& t1, const Test& t2) 

您的操作員需要參考const Test對象。您只能通過對const限定類型的引用來調用const合格的成員函數。

set<Test>::iterator it = s.begin() 

std::set的元素是不可變的:您無法更改它們。因此,迭代器到std::set始終是const限定類型的對象。

+0

關於「迭代器一個std ::組總是到對象的常量限定類型。」:即在C的任何版本指定被++標準或這取決於標準庫開發人員? – 2011-05-18 04:03:36

+1

@Eugen:它在標準的第23.2.4p6節中指定(在C++ 0x中,編號可能在早期版本中有所不同)。 – 2011-05-18 04:11:17

+0

@Eugen:在(C++ 0x FDIS)中指定23.2.4 p5關聯容器中的鍵是不可變的&p6'對於關聯容器,其中 的值類型與鍵類型相同,迭代器和const_iterator都是常量迭代器「。 – Xeo 2011-05-18 04:14:41

2
const Test& t1 

使t1不變,也就是說,它不能通過該引用進行更改。現在,您對該對象調用的任何函數都可能改變其內部狀態 - const不允許!

這是怎麼解決的?只需將不會改變內部狀態的函數標記爲const!這意味着,它們可以在const對象/引用/指針上調用。
這就是爲什麼你需要constgetId函數,以確保你不會改變任何內部狀態。

int getId() const { return id;}; 

編輯:當然,這同樣適用於std::set,但我不會去,作爲其他的答案已經這樣做了。

3

set::iterator只給出const訪問元素,變化可能會影響集合中元素的相對順序 - 不變的,它需要保護(也就是說,如果你在設置更改元素,可能會損壞的假設排序設置中的元素,以及未來的查找,插入等將不會如預期的那樣可靠地工作)。因此,只有const成員函數可以通過iterator對元素訪問進行調用。

這有點令人困惑,因爲對於其他一些容器,const_iteratoriterator的選擇決定了授予的訪問權限。

1

你只能在const對象上調用const成員函數。

set<Test>::iterator it = s.begin(); 

返回一個const對象,所以你只能調用這個對象的const類型的成員函數。

+0

真的,'* it'返回一個const對象。迭代器本身不是'const'。 – 2011-05-18 04:12:08

0

運算符()在其參數列表中有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 
    }