const-методы
Объект, объявленный с const, менять нельзя. Он похож на экспонат под стеклом: подойти и прочитать табличку можно, а переставить что-то внутри нельзя. Аналогия кончается на том, что стекло ставит не музей, а объявление: тот же класс без const у объекта можно менять.
У класса, однако, есть методы, и одни только читают поля, а другие их меняют. Какие из них можно вызвать у объекта под стеклом? Компилятор решает это по объявлению метода, а не по его телу:
#include <iostream>
class Temperature {
public:
Temperature(int celsius) : celsius_(celsius) {}
int celsius() const { return celsius_; }
void warm() { ++celsius_; }
private:
int celsius_;
};
int main() {
const Temperature t(20);
std::cout << t.celsius() << '\n'; // 20
}const-методы
У константного объекта, как и через ссылку const T&, можно вызвать только const-методы. Это методы со словом const после списка параметров, как int celsius() const.
Слово const здесь — обещание: метод не меняет объект. Компилятор держит его так:
- внутри
const-метода объект тоже константный, и присвоить значение полю там нельзя; - исключение — поле, объявленное со словом
mutable: его можно менять и вconst-методе. Пример — счётчик вызовов, который не меняет смысла объекта.
Для const Temperature t(20); вызов t.celsius() компилируется, а t.warm() — нет: warm объявлен без const, и компилятор не пускает его к экспонату.
Поэтому метод, который только читает поля, объявляют const. Его можно вызвать для любого объекта, и константного, и обычного.
Зачем это нужно? Большие объекты передают в функции по константной ссылке const T&, чтобы не копировать их. Внутри такой функции объект — тот же экспонат под стеклом. Если методы чтения объявлены без const, функция не сможет вызвать даже их.
Этот вопрос часто задают на собеседовании: что значит const после списка параметров. Ответ: метод не меняет объект, для которого его вызвали.
Частая ошибка
Метод только читает поле, но объявлен без const:
class Temperature {
public:
Temperature(int celsius) : celsius_(celsius) {}
int celsius() { return celsius_; }
private:
int celsius_;
};
int twice(const Temperature& t) {
return t.celsius() * 2; // ✗
}error: 'this' argument to member function 'celsius' has type 'const Temperature', but function is not marked constПараметр t — константная ссылка, а celsius() не обещает оставить объект неизменным, поэтому вызов не компилируется. Добавьте const после списка параметров: int celsius() const.
Главное
- У константного объекта и через
const T&можно вызвать толькоconst-методы. constпосле списка параметров обещает, что метод не меняет объект.- Компилятор проверяет объявление метода, а не его тело.
- Метод, который только читает поля, объявляйте
const.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.