C++ 错误:将 xxx 作为 xxx 的“this”参数传递会丢弃限定符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5973427/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:16:16  来源:igfitidea点击:

error: passing xxx as 'this' argument of xxx discards qualifiers

c++

提问by JASON

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

In line:

排队:

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

It give an error that:

它给出了一个错误:

../main.cpp:35: error: passing 'const StudentT' as 'this' argument of 'int StudentT::getId()' discards qualifiers

../main.cpp:35: error: passing 'const StudentT' as 'this' argument of 'std::string StudentT::getName()' discards qualifiers

../main.cpp:35: 错误:将“const StudentT”作为“int StudentT::getId()”的“this”参数传递会丢弃限定符

../main.cpp:35: 错误:将“const StudentT”作为“std::string StudentT::getName()”的“this”参数传递会丢弃限定符

What's wrong with this code? Thank you!

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

回答by Nawaz

The objects in the std::setare stored as const StudentT. So when you try to call getId()with the constobject 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 safeassumption 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.

中的对象std::set存储为const StudentT. 因此,当您尝试getId()使用const对象调用时,编译器会检测到问题,主要是您在 const 对象上调用了一个非常量成员函数,这是不允许的,因为非常量成员函数不允许不修改对象;所以编译器会做出一个安全的假设,getId()可能会尝试修改对象,但同时,它也注意到该对象是 const;所以任何修改 const 对象的尝试都应该是一个错误。因此编译器会生成错误消息。

The solution is simple: make the functions const as:

解决方案很简单:使函数 const 为:

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

This is necessary because now you can call getId()and getName()on const objects as:

这是必要的,因为现在您可以调用getId()getName()在 const 对象上作为:

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 a sidenote, you should implement operator<as :

作为旁注,您应该实现operator<为:

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

Note parameters are now constreference.

注意参数现在是const参考。

回答by Fred Larson

Member functions that do not modify the class instance should be declared as const:

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

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

Anytime you see "discards qualifiers", it's talking about constor volatile.

每当您看到“丢弃限定符”时,它都在谈论constvolatile

回答by Eugen Constantin Dinca

Actually the C++ standard (i.e. C++ 0x draft) says (tnx to @Xeo & @Ben Voigt for pointing that out to me):

实际上,C++ 标准(即C++ 0x 草案)说(tnx 到 @Xeo 和 @Ben Voigt 向我指出这一点):

23.2.4Associative containers
5For 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.
6iterator 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.

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

So VC++ 2008 Dinkumware implementation is faulty.

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



Old answer:

旧答案:

You got that error because in certain implementations of the std lib the set::iteratoris the same as set::const_iterator.

您收到该错误是因为在 std lib 的某些实现中,set::iterator它与set::const_iterator.

For example libstdc++ (shipped with g++) has it (see herefor the entire source code):

例如 libstdc++(随 g++ 一起提供)就有它(完整源代码见这里):

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

And in SGI's docsit states:

在 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.)

On the other hand VC++ 2008 Express compiles your code without complaining that you're calling non const methods on set::iterators.

另一方面,VC++ 2008 Express 编译您的代码时不会抱怨您在set::iterators上调用非 const 方法。

回答by Jayhello

Let's me give a more detail example. As to the below struct:

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

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

在此处输入图片说明

As you see the above, the IDE(CLion), will give tips Non-const function 'getCount' is called on the const object. In the method addcountis declared as const object, but the method getCountis not const method, so count.getCount()may change the members in count.

如您所见,IDE(CLion) 会给出提示Non-const function 'getCount' is called on the const object。在方法中addcount被声明为const对象,但该方法getCount不是const方法,所以count.getCount()可能会改变中的成员count

Compile error as below(core message in my compiler):

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

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

To solve the above problem, you can:

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

  1. change the method uint32_t getCount(){...}to uint32_t getCount() const {...}. So count.getCount()won't change the members in count.
  1. 将方法更改uint32_t getCount(){...}uint32_t getCount() const {...}. 所以count.getCount()不会改变count.

or

或者

  1. change uint32_t add(const Count& count){...}to uint32_t add(Count& count){...}. So countdon't care about changing members in it.
  1. 更改uint32_t add(const Count& count){...}uint32_t add(Count& count){...}. 所以count不要在意改变里面的成员。

As to you problem, objects in the std::set are stored as const StudentT, but the method getIdand getNameare not const, so you give the above error.

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

You can also see this question Meaning of 'const' last in a function declaration of a class?for more detail.

您还可以在类的函数声明中最后看到这个问题“const”的含义?了解更多详情。