首页 文章

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

提问于
浏览
353
#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'参数会丢弃限定符

这段代码出了什么问题?谢谢!

4 回答

  • 70

    std::set 中的对象存储为 const StudentT . 因此,当您尝试使用 const 对象调用 getId() 时,编译器会检测到问题,主要是您在const对象上调用非const成员函数,这是不允许的,因为非const成员函数没有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<

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

    注意参数现在是 const 参考 .

  • 5

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

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

    无论何时你看到"discards qualifiers",它都在谈论 constvolatile .

  • 400

    实际上C标准(即C++ 0x draft)说(tnx到@Xeo和@Ben Voigt向我指出):

    23.2.4关联容器5对于set和multiset,值类型与键类型相同 . 对于map和multimap,它等于pair . 关联容器中的键是不可变的 . 6关联容器的迭代器是双向迭代器类别 . 对于值类型与键类型相同的关联容器,iterator和const_iterator都是常量迭代器 . 未指定迭代器和const_iterator是否是同一类型 .

    因此VC 2008 Dinkumware的实现是错误的 .


    Old answer:

    你得到了这个错误,因为在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方法 .

  • 0

    让我给出一个更详细的例子 . 至于下面的结构:

    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 中的成员 .

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

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

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

    • 将方法 uint32_t getCount(){...} 更改为 uint32_t getCount() const {...} . 所以 count.getCount() 不会改变 count 中的成员 .

    要么

    • uint32_t add(const Count& count){...} 更改为 uint32_t add(Count& count){...} . 所以 count 并不关心改变其中的成员 .

    至于你的问题,std :: set中的对象存储为const StudentT,但方法 getIdgetName 不是const,所以你给出了上面的错误 .

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

相关问题