#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:错误:传递'const StudentT'作为'int StudentT::getId()'的'this'参数会丢弃限定符
../main.cpp:35:错误:传递'const StudentT'作为'std::string StudentT::getName()'的'this'参数会丢弃限定符
这段代码有什么问题?谢谢你!
The objects in the std::set are stored as const StudentT. So when you try to call getId() with the const object the compiler detects a problem, mainly you're calling a non-const member function on const object which is not allowed because non-const member functions make NO PROMISE not to modify the object; so the compiler is going to make a safe assumption that getId() might attempt to modify the object but at the same time, it also notices that the object is const; so any attempt to modify the const object should be an error. Hence compiler generates an error message.
解决方案很简单:将函数设为const as:
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
}
作为旁注,你应该实现操作符< As:
inline bool operator< (const StudentT & s1, const StudentT & s2)
{
return s1.getId() < s2.getId();
}
注形参现在是const引用。
The objects in the std::set are stored as const StudentT. So when you try to call getId() with the const object the compiler detects a problem, mainly you're calling a non-const member function on const object which is not allowed because non-const member functions make NO PROMISE not to modify the object; so the compiler is going to make a safe assumption that getId() might attempt to modify the object but at the same time, it also notices that the object is const; so any attempt to modify the const object should be an error. Hence compiler generates an error message.
解决方案很简单:将函数设为const as:
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
}
作为旁注,你应该实现操作符< As:
inline bool operator< (const StudentT & s1, const StudentT & s2)
{
return s1.getId() < s2.getId();
}
注形参现在是const引用。
实际上,c++标准(即c++ 0x草案)说(tnx @Xeo和@Ben Voigt指出了这一点):
23.2.4 Associative containers
5 For set and multiset the value type
is the same as the key type. For map
and multimap it is equal to pair. Keys in an associative
container are immutable.
6 iterator of
an associative container is of the
bidirectional iterator category. For
associative containers where the value
type is the same as the key type, both
iterator and const_iterator are
constant iterators. It is unspecified
whether or not iterator and
const_iterator are the same type.
所以vc++ 2008 Dinkumware实现是错误的。
旧的回答:
你得到这个错误是因为在std lib的某些实现中,set::iterator与set::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::迭代器上调用了非const方法。
让我举一个更详细的例子。对于下面的结构:
struct Count{
uint32_t c;
Count(uint32_t i=0):c(i){}
uint32_t getCount(){
return c;
}
uint32_t add(const Count& count){
uint32_t total = c + count.getCount();
return total;
}
};
如你所见,IDE(CLion)将给出提示,非const函数“getCount”在const对象上被调用。在该方法中,add count被声明为const对象,但getCount方法不是const方法,因此count.getCount()可能会改变count中的成员。
编译错误如下(核心消息在我的编译器):
error: passing 'const xy_stl::Count' as 'this' argument discards qualifiers [-fpermissive]
要解决上述问题,您可以:
改变uint32_t getCount()方法{…} to uint32_t getCount() const{…}。因此count. getcount()不会改变count中的成员。
or
修改uint32_t add(const count & count){…} to uint32_t add(count & count){…}。所以count并不关心其中成员的变化。
至于你的问题,std::set中的对象被存储为const StudentT,但方法getId和getName不是const,所以你给出了上述错误。
你也可以看到这个问题“const”在类的函数声明中的最后含义?更多细节。