Поиск…


Синтаксис

  • 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'; 
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow