c++ - 錯誤:將XXX作為xxx的“this”參數丟棄限定符


#include <iostream>
#include <set>

using namespace std;

class StudentT {

public:
    int id;
    string name;
public:
    StudentT(int _id, string _name) : id(_id), name(_name) {
    }
    int getId() {
        return id;
    }
    string getName() {
        return name;
    }
};

inline bool operator< (StudentT s1, StudentT s2) {
    return  s1.getId() < s2.getId();
}

int main() {

    set<StudentT> st;
    StudentT s1(0, "Tom");
    StudentT s2(1, "Tim");
    st.insert(s1);
    st.insert(s2);
    set<StudentT> :: iterator itr;
    for (itr = st.begin(); itr != st.end(); itr++) {
        cout << itr->getId() << " " << itr->getName() << endl;
    }
    return 0;
}

一致:

cout << itr->getId() << " " << itr->getName() << endl;

它給出了一個錯誤:

../main.cpp:35:錯誤:作為'int'StudentT :: getId()的'this'參數傳遞'const StudentT'丟棄限定符

../main.cpp:35:錯誤:將'const StudentT'作為'std :: string'的參數傳遞給StudentT :: getName()'拋棄限定符

這個代碼有什麼問題? 謝謝!



Answers


std::set中的對象存儲為const StudentT 。 所以當你試圖用const對象調用getId() ,編譯器檢測到一個問題,即你在const對像上調用一個非const成員函數,這是不允許的,因為非const成員函數使得NO PROMISE不能修改目的; 所以編譯器會做一個安全的假設, getId()可能試圖修改對象,但同時也注意到對像是const的; 所以任何修改const對象的嘗試都應該是錯誤的。 因此編譯器生成錯誤信息。

解決方法很簡單:使函數的const為:

int getId() const {
    return id;
}
string getName() const {
    return name;
}

這是必要的,因為現在你可以在const對像上調用getId()getName()

void f(const StudentT & s)
{
     cout << s.getId();   //now okay, but error with your versions
     cout << s.getName(); //now okay, but error with your versions
}

作為旁注,你應該實現operator< as:

inline bool operator< (const StudentT & s1, const StudentT & s2)
{
    return  s1.getId() < s2.getId();
}

注意參數現在是const引用。




不修改類實例的成員函數應聲明為const

int getId() const {
    return id;
}
string getName() const {
    return name;
}

任何時候你看到“丟棄限定符”,它是在談論constvolatile




實際上,C ++標準(即C ++ 0x草案 )說(tnx to @Xeo&@Ben Voigt指出了我):

23.2.4關聯容器
5對於set和multiset,其值類型與鍵類型相同。 對於map和multimap,它等於pair。 關聯容器中的鍵是不可變的。
6關聯容器的迭代器是雙向迭代器類別。 對於值類型與鍵類型相同的關聯容器,iterator和const_iterator都是常量迭代器。 iterator和const_iterator是否是相同的類型是未指定的。

所以VC ++ 2008 Dinkumware實現有問題。

老答案:

你有這個錯誤,因為在std庫的某些實現中, set::iteratorset::const_iterator是一樣的。

例如libstdc ++(附帶g ++)有它(參見這裡的整個源代碼):

typedef typename _Rep_type::const_iterator            iterator;
typedef typename _Rep_type::const_iterator            const_iterator;

在SGI的文件中,它指出:

iterator       Container  Iterator used to iterate through a set.
const_iterator Container  Const iterator used to iterate through a set. (Iterator and const_iterator are the same type.)

另一方面,VC ++ 2008 Express編譯你的代碼而不抱怨你在set::iterator上調用非const方法。










Tags