错误:将 const xxx 传递为“this”成员函数的参数丢弃限定符

发布于 2024-11-06 06:54:17 字数 1122 浏览 6 评论 0原文

#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”参数传递会丢弃限定符

这段代码有什么问题?

#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

What's wrong with this code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

终止放荡 2024-11-13 06:54:17

std::set 中的对象存储为 const StudentT。因此,当您尝试使用 const 对象调用 getId() 时,编译器会检测到问题,主要是您在 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 引用。

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.

The solution is simple: make the functions const as:

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:

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 :

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

Note parameters are now const reference.

三生路 2024-11-13 06:54:17

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

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

任何时候您看到“discards qualifiers”,它都在谈论 constvolatile

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

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

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

倾城°AllureLove 2024-11-13 06:54:17

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

23.2.4 关联容器
5 对于集合和多重集合值类型
与密钥类型相同。对于地图
而multimap则等于pair。关联中的键
容器是不可变的。
6 迭代器
关联容器是
双向迭代器类别。为了
关联容器,其中值
type 与 key 类型相同,两者
迭代器和 const_iterator 是
常量迭代器。未指定
是否迭代器和
const_iterator 是相同的类型。

所以 VC++ 2008 Dinkumware 实现是错误的。


旧答案:

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

例如 libstdc++ (随 g++ 一起提供)有它(请参阅此处 整个源代码):

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 上调用非常量方法。

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

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.

So VC++ 2008 Dinkumware implementation is faulty.


Old answer:

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

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

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

And in SGI's docs it states:

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.

撩心不撩汉 2024-11-13 06:54:17

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

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 对象上调用非 const 函数“getCount”。在方法 add 中,count 被声明为 const 对象,但方法 getCount 不是 const 方法,因此 count.getCount() 可能会更改 count 中的成员。

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

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 不关心其中成员的更改。

至于您的问题, std::set 中的对象存储为 const StudentT,但方法 getIdgetName 不是 const,因此您给出了上述错误。

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

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 add count is declared as const object, but the method getCount is not const method, so count.getCount() may change the members in 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.

or

  1. change uint32_t add(const Count& count){...} to uint32_t add(Count& count){...}. So count don't care about changing members in it.

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文