Ошибка: передача xxx в качестве аргумента 'this' в xxx отбрасывает квалификаторы
#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' в качестве аргумента 'this' для int StudentT::getId()'отменяет квалификаторы
../main.cpp:35: ошибка: передача 'const StudentT' в качестве 'this' аргумента 'std::string StudentT::getName()' отменяет квалификаторы
Что не так с этим кодом? Спасибо!
4 ответа
Объекты в std::set
хранятся как const StudentT
, Поэтому, когда вы пытаетесь позвонить getId()
с const
объект, который компилятор обнаруживает проблему, в основном вы вызываете неконстантную функцию-член для константного объекта, что недопустимо, потому что неконстантные функции-члены НЕ ОБЕЩАЮТ, что не изменяют объект; поэтому компилятор сделает безопасное предположение, что getId()
может пытаться изменить объект, но в то же время он также замечает, что объект является const; поэтому любая попытка изменить объект const должна быть ошибкой. Следовательно, компилятор генерирует сообщение об ошибке.
Решение простое: сделать функции такими же:
int getId() const {
return id;
}
string getName() const {
return name;
}
Это необходимо, потому что теперь вы можете позвонить 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
ссылка.
Функции-члены, которые не изменяют экземпляр класса, должны быть объявлены как const
:
int getId() const {
return id;
}
string getName() const {
return name;
}
Каждый раз, когда вы видите "отбрасывает квалификаторы", это говорит о const
или же volatile
,
На самом деле стандарт C++ (то есть черновик C++ 0x) гласит (tnx to @Xeo & @Ben Voigt за указание на это мне):
23.2.4 Ассоциативные контейнеры
5 Для set и multiset тип значения совпадает с типом ключа. Для карты и мультикарты он равен паре. Ключи в ассоциативном контейнере являются неизменяемыми.
6 итератор ассоциативного контейнера относится к категории двунаправленных итераторов. Для ассоциативных контейнеров, в которых тип значения совпадает с типом ключа, итератор и const_iterator являются постоянными итераторами. Не определено, являются ли итераторы и const_iterator одинаковыми.
Таким образом, реализация Dinkumware в VC++ 2008 неисправна.
Старый ответ:
Вы получили эту ошибку, потому что в некоторых реализациях 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::iterator
s.
Позвольте мне привести более подробный пример. Что касается структуры ниже:
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), даст советы 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, но метод getId
а также getName
не являются константными, поэтому вы даете вышеуказанную ошибку.
Вы также можете увидеть этот вопрос Значение 'const' последний в объявлении функции класса? для более подробной информации.