C++
ключевое слово const
Поиск…
Синтаксис
- const Тип myVariable = initial; // Объявляет константную переменную; не может быть изменено
- const Тип & myReference = myVariable; // Объявляет ссылку на константную переменную
- const Тип * myPointer = & myVariable; // Объявляет указатель на константу. Указатель может меняться, но основной элемент данных не может быть изменен с помощью указателя
- Тип * const myPointer = & myVariable; // Объявляет указатель const. Указатель не может быть переназначен, чтобы указать на что-то еще, но базовый элемент данных можно изменить
- const Тип * const myPointer = & myVariable; // Объявляет const-указатель-const-const.
замечания
Переменная помечается как const
не может быть изменен 1. Попытка вызвать любые неконстантные операции над ним приведет к ошибке компилятора.
1: Ну, его можно изменить через const_cast
, но вы почти никогда не должны использовать это
Константные локальные переменные
Декларация и использование.
// a is const int, so it can't be changed
const int a = 15;
a = 12; // Error: can't assign new value to const variable
a += 1; // Error: can't assign new value to const variable
Связывание ссылок и указателей
int &b = a; // Error: can't bind non-const reference to const variable
const int &c = a; // OK; c is a const reference
int *d = &a; // Error: can't bind pointer-to-non-const to const variable
const int *e = &a // OK; e is a pointer-to-const
int f = 0;
e = &f; // OK; e is a non-const pointer-to-const,
// which means that it can be rebound to new int* or const int*
*e = 1 // Error: e is a pointer-to-const which means that
// the value it points to can't be changed through dereferencing e
int *g = &f;
*g = 1; // OK; this value still can be changed through dereferencing
// a pointer-not-to-const
Указатели констант
int a = 0, b = 2;
const int* pA = &a; // pointer-to-const. `a` can't be changed through this
int* const pB = &a; // const pointer. `a` can be changed, but this pointer can't.
const int* const pC = &a; // const pointer-to-const.
//Error: Cannot assign to a const reference
*pA = b;
pA = &b;
*pB = b;
//Error: Cannot assign to const pointer
pB = &b;
//Error: Cannot assign to a const reference
*pC = b;
//Error: Cannot assign to const pointer
pC = &b;
Функции члена-члена
Функции-члены класса могут быть объявлены const
, который сообщает компилятору и будущим читателям, что эта функция не будет изменять объект:
class MyClass
{
private:
int myInt_;
public:
int myInt() const { return myInt_; }
void setMyInt(int myInt) { myInt_ = myInt; }
};
В функции-члене const
this
указатель эффективно представляет собой const MyClass *
вместо MyClass *
. Это означает, что вы не можете изменять какие-либо переменные-члены внутри функции; компилятор выдаст предупреждение. Поэтому setMyInt
не может быть объявлен const
.
Вы должны почти всегда отмечать функции-члены как const
когда это возможно. На const MyClass
можно вызвать только функции const
члена.
static
методы не могут быть объявлены как const
. Это связано с тем, что статический метод принадлежит классу и не вызывается на объект; поэтому он никогда не может изменять внутренние переменные объекта. Поэтому объявление static
методов как const
будет излишним.
Избегание дублирования кода в методах const и non-const getter.
В C ++ методы, которые отличаются только const
могут быть перегружены. Иногда может потребоваться две версии getter, которые возвращают ссылку на некоторую часть.
Пусть Foo
- класс, который имеет два метода, которые выполняют идентичные операции и возвращает ссылку на объект типа Bar
:
class Foo
{
public:
Bar& GetBar(/* some arguments */)
{
/* some calculations */
return bar;
}
const Bar& GetBar(/* some arguments */) const
{
/* some calculations */
return bar;
}
// ...
};
Единственная разница между ними заключается в том, что один метод является неконстантным и возвращает неконстантную ссылку (которую можно использовать для изменения объекта), а вторая является константой и возвращает константу ссылки.
Чтобы избежать дублирования кода, возникает соблазн вызвать один метод из другого. Однако мы не можем вызывать метод non-const из константы. Но мы можем вызвать метод const из неконстантного. Это потребует использования «const_cast» для удаления спецификатора const.
Решение:
struct Foo
{
Bar& GetBar(/*arguments*/)
{
return const_cast<Bar&>(const_cast<const Foo*>(this)->GetBar(/*arguments*/));
}
const Bar& GetBar(/*arguments*/) const
{
/* some calculations */
return foo;
}
};
В приведенном выше коде мы вызываем const-версию GetBar
из не-const GetBar
, отбрасывая это на тип const: const_cast<const Foo*>(this)
. Поскольку мы вызываем метод const из не-const, сам объект не является константой, и исключение const допускается.
Изучите следующий более полный пример:
#include <iostream>
class Student
{
public:
char& GetScore(bool midterm)
{
return const_cast<char&>(const_cast<const Student*>(this)->GetScore(midterm));
}
const char& GetScore(bool midterm) const
{
if (midterm)
{
return midtermScore;
}
else
{
return finalScore;
}
}
private:
char midtermScore;
char finalScore;
};
int main()
{
// non-const object
Student a;
// We can assign to the reference. Non-const version of GetScore is called
a.GetScore(true) = 'B';
a.GetScore(false) = 'A';
// const object
const Student b(a);
// We still can call GetScore method of const object,
// because we have overloaded const version of GetScore
std::cout << b.GetScore(true) << b.GetScore(false) << '\n';
}