错误:将xxx作为xxx的'this'参数传递丢弃限定符

时间:2011-05-12 04:52:57

标签: c++

#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的'this'参数传递给StudentT :: getName()'丢弃限定符

这段代码有什么问题?谢谢!

4 个答案:

答案 0 :(得分:438)

std::set中的对象存储为const StudentT。因此,当您尝试使用getId()对象调用const时,编译器会检测到问题,主要是您在const对象上调用非const成员函数,这是不允许的,因为非const成员函数使不承诺不修改对象;所以编译器会做出安全假设,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<实现为:

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

注意参数现在是const参考。

答案 1 :(得分:74)

不修改类实例的成员函数应声明为const

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

只要您看到“丢弃限定词”,就会谈论constvolatile

答案 2 :(得分:5)

实际上C ++标准(即C++ 0x draft)说(tnx to @Xeo&amp; @Ben Voigt指出这一点):

  

23.2.4 关联容器
   5 对于set和multiset的值类型   与键类型相同。对于地图   和multimap它等于pair。关联中的键   容器是不可变的    6 迭代器   关联容器是   双向迭代器类。对于   关联容器所在的值   type与key类型相同   iterator和const_iterator是   常数迭代器。它没有具体说明   是否迭代器和   const_iterator是相同的类型。

所以VC ++ 2008 Dinkumware实现有问题。


旧回答:

您收到了该错误,因为在std lib的某些实现中,set::iteratorset::const_iterator相同。

例如libstdc ++(随g ++提供)有它(有关完整源代码,请参阅here):

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

在SGI的docs中声明:

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方法。

答案 3 :(得分:1)

让我举个更详细的例子。至于下面的结构:

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;
    }
};

enter image description here

如您所见,IDE(CLion)将提供提示Non-const function 'getCount' is called on the const object。方法add count被声明为const对象,但方法getCount不是const方法,因此count.getCount()可能会更改count中的成员。< / p>

编译错误如下(编译器中的核心消息):

error: passing 'const xy_stl::Count' as 'this' argument discards qualifiers [-fpermissive]

要解决上述问题,您可以:

  1. 将方法uint32_t getCount(){...}更改为uint32_t getCount() const {...}。因此count.getCount()不会更改count中的成员。
    1. uint32_t add(const Count& count){...}更改为uint32_t add(Count& count){...}。所以count并不关心改变其中的成员。
    2. 至于你的问题,std :: set中的对象存储为const StudentT,但方法getIdgetName不是const,所以你给出了上面的错误。

      您还可以查看此问题Meaning of 'const' last in a function declaration of a class?以获取更多详细信息。