объяснение «передачи const XXX, поскольку это игнорирует квалификаторы»?

#c

#c

Вопрос:

У меня есть класс

 class Test {
public:
    void f() {}
    void g() const { f(); }
};
  

который не может скомпилироваться с

ошибка: передача ‘const Test’ в качестве аргумента ‘this’ отбрасывает квалификаторы (при вызове void Test ::f())

Я понимаю, что я не должен вызывать неконстантный f из const g . Однако я не понимаю содержания сообщения. Откуда берется const Test объект и какие квалификаторы отбрасываются ( f() не имеет никаких квалификаторов)??

Комментарии:

1. this Указатель передается в функции-члены автоматически (как self в python). Вероятно, вы вызвали const функцию-член g , внутри которой вы вызываете неконстантную функцию-член f .

2. @Yashas: спасибо. Я так и подозревал, но почему это const Test указатель. const преобразует ли функция-член это автоматически??

3. const квалификатор в функциях-членах применяется к этому экземпляру объекта, а не к самой функции

4. @Yashas Опять же, не отвечайте в разделе комментариев. Наведите курсор мыши на ссылку «добавить комментарий» (или прочитайте заголовок раздела ниже), если вы мне не верите.

5. Действительно. Ответы в разделе ответов, пожалуйста, @Yashas.

Ответ №1:

this Указатель в const функции-члене имеет тип const Test* . Вот как const логически обеспечивается доступ только для участников. Это своего рода деталь реализации, но довольно разумная.

Когда вы пытаетесь вызвать f() , думайте об этом как о передаваемом аргументе скрытой функции. Аргументом скрытой функции является this указатель. f() ожидает Test* , но вы передаете его const Test* . Преобразование между ними привело бы к «отбрасыванию квалификаторов», т. Е. пришлось бы отбросить const , что недопустимо.

Я согласен с вами, что диагностика немного эзотерична, но в основном это всегда означает «вы пытаетесь сделать не- const вещь в const контексте».

Комментарии:

1. Да, приятно иметь ответы в разделе ответов, поскольку их можно рецензировать. На мой взгляд, это хороший ответ. Проголосуйте за.

2. @спасибо. Когда я вызываю функцию const для неконстантного объекта, откуда берется const Test * ? this создается для вызова функции??

3. @blue_note Да, точно, это волшебный указатель, который вы получаете бесплатно автоматически. (В конечном счете, это действительно «исходит» с сайта вызова, где вы указали объект для вызова функции, с const дополнительным добавлением по пути, если это const вызванная вами функция)

4. @Bathsheba Все реже рискует публиковать ответы здесь. Я действительно не понимаю. Не может быть проще! Некоторые другие сайты SE действительно расправились с этим, но SO по какой-то причине сопротивляется. : (Лично я думаю, что иметь аккуратный дом более гостеприимно, чем большой старый беспорядок

Ответ №2:

Невозможно 1 вызвать f() из g() как g() есть const (что означает, что неявный this указатель является const ), а f() нет const .

Следовательно, компиляция завершается неудачей, в вашем случае с полезной диагностикой.


1 Ну, не совсем невозможно: взлом, поведение которого могло быть неопределенным, если объект был создан как const есть

 void g() const { const_cast<Test*>(this)->f(); }