error: передача xxx как «этого» аргумента xxx отбрасывает квалификаторы

#include  #include  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 st; StudentT s1(0, "Tom"); StudentT s2(1, "Tim"); st.insert(s1); st.insert(s2); set :: iterator itr; for (itr = st.begin(); itr != st.end(); itr++) { cout <getId() << " " <getName() << endl; } return 0; } 

В очереди:

 cout <getId() << " " <getName() << endl; 

Это дает ошибку:

../main.cpp:35: ошибка: передача ‘const StudentT’ как ‘this’ аргумента ‘int StudentT :: getId ()’ отбрасывает квалификаторы

../main.cpp:35: error: передать ‘const StudentT’ как ‘this’ аргумент ‘std :: string StudentT :: getName ()’ отбрасывает квалификаторы

Что случилось с этим кодом? Спасибо!

Объекты в std::set сохраняются как const StudentT . Поэтому, когда вы пытаетесь вызвать getId() с объектом const компилятор обнаруживает проблему, в основном вы вызываете функцию non-const member в объекте const, которая не разрешена, потому что не-const-функции-члены не делают НИКАКОГО ОБЯЗАТЕЛЬСТВА, чтобы не изменять объект; поэтому компилятор собирается сделать безопасное предположение, что getId() может попытаться изменить объект, но в то же время он также замечает, что объект const; поэтому любая попытка изменить объект const должна быть ошибкой. Следовательно, компилятор генерирует сообщение об ошибке.

Решение простое: сделайте функции const следующими:

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

Это необходимо, потому что теперь вы можете вызвать 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 } 

В качестве побочного элемента вы должны реализовать operator< as:

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

Параметры примечаний теперь являются опорными.

Функции-члены, которые не изменяют экземпляр classа, должны быть объявлены как const :

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

Каждый раз, когда вы видите «отбрасывает квалификаторы», речь идет о const или volatile .

На самом деле стандарт C ++ (например, C ++ 0x draft ) говорит (tnx to @Xeo & @Ben Voigt для указания на это мне):

23.2.4 Ассоциативные контейнеры
5 Для set и multiset тип значения совпадает с типом ключа. Для карты и мультимапа он равен паре. Ключи в ассоциативном контейнере неизменяемы.
6 iterator ассоциативного контейнера относится к категории двунаправленного iteratorа. Для ассоциативных контейнеров, где тип значения совпадает с типом ключа, оба iteratorа и const_iterator являются постоянными iteratorами. Не указано, является ли 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 компилирует ваш код, не жалуясь, что вы вызываете методы non const в 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] 

Чтобы решить вышеуказанную проблему, вы можете:

  1. измените метод uint32_t getCount(){...} на uint32_t getCount() const {...} . Поэтому count.getCount() не будет изменять членов в count .

или

  1. change uint32_t add(const Count& count){...} to uint32_t add(Count& count){...} . Поэтому count не заботится об изменении членов в нем.

Что касается вас, объекты в std :: set сохраняются как const StudentT, но метод getId и getName не являются getName , поэтому вы приводите приведенную выше ошибку.

Вы также можете увидеть этот вопрос. Значение ‘const’ last в объявлении функции classа? для более подробной информации.

  • Какая польза от деструктора как частного?
  • В чем преимущества использования C # vs F # или F # vs C #?
  • Можете ли вы поймать собственное исключение в коде C #?
  • C # Ковариация по типам возвратов подclassа
  • C # как создать значение Guid?
  • Как создать битмап из массива байтов?
  • C # переключатель типа
  • Как я могу получить положение текстового поля, которое было нажато?
  • Зачем использовать ключевое слово params?
  • MVC 3: Как визуализировать представление без его страницы макета при загрузке через ajax?
  • Как защитить ресурсы, которые могут использоваться в многопоточной или асинхронной среде?
  • Давайте будем гением компьютера.