Использование 'const' в функциях класса

Я видел много использования ключевого слова const после функций в классах, поэтому я хотел знать, о чем это было. Я прочитал что-то здесь: http://duramecho.com/ComputerInformation/WhyHowCppConst.html.

В нем говорится, что const используется, потому что функция "может пытаться изменить любые переменные-члены в объекте". Если это так, то следует использовать его везде, потому что я не хочу, чтобы ЛЮБЫЕ из переменных-членов были изменены или изменены каким-либо образом.

class Class2
{ void Method1() const;
  int MemberVariable1;} 

Итак, каково реальное определение и использование const?

Ответ 1

Метод const может быть вызван в const-объекте:

class CL2
{
public:
    void const_method() const;
    void method();

private:
    int x;
};


const CL2 co;
CL2 o;

co.const_method();  // legal
co.method();        // illegal, can't call regular method on const object
o.const_method();   // legal, can call const method on a regulard object
o.method();         // legal

Кроме того, он также сообщает компилятору, что метод const не должен изменять состояние объекта и будет ловить эти проблемы:

void CL2::const_method() const
{
    x = 3;   // illegal, can't modify a member in a const object
}

Существует исключение из вышеприведенного правила с использованием изменяемого модификатора, но сначала вы должны получить добро на корректность const, прежде чем отправиться на эту территорию.

Ответ 2

const при подключении к методу нестатического класса сообщает компилятору, что ваша функция не изменяет внутреннее состояние объекта.

Это полезно двумя способами:

  • Если вы пишете код, который изменяет внутреннее состояние в вашем методе const, компилятор ловит ошибку, перемещая ошибку программирования из времени выполнения во время компиляции.
  • Если клиентский код вызывает метод non-const на указателе константы, компилятор ловит ошибку, гарантируя, что поддерживается "цепочка не изменяющихся вещей".

Обычно вы хотите объявить все не-mutating нестатические методы класса как const. Это позволяет вызывать код для использования спецификатора const в указателях, и это помогает ломать ошибки.

Типичный С++: вы можете объявить переменную-член класса "mutable", а затем изменить ее даже из метода const.

Ответ 3

Другие ответили на техническую сторону вашего вопроса о функциях const member, но здесь есть более широкая картина - и это идея const correctness.

Короче говоря, константная корректность - это разъяснение и обеспечение соблюдения семантики вашего кода. Возьмем простой пример. Посмотрите на объявление этой функции:

bool DoTheThing(char* message);

Предположим, что кто-то еще написал эту функцию, и вам нужно позвонить ей. Знаете ли вы, что DoTheThing() делает для вашего буфера char? Возможно, он просто записывает сообщение в файл или, возможно, меняет строку. Вы не можете сказать, что означает семантика вызова, просто взглянув на объявление функции. Если функция не изменяет строку, то объявление является некорректным.

Здесь также правильное значение для правильной настройки ваших функций. А именно, в зависимости от контекста вызова, вы не сможете вызвать const-некорректные функции без какой-либо обмана. Например, предположим, что вы знаете, что DoTheThing() не изменяет содержимое переданной ему строки, и у вас есть этот код:

void MyFunction()
{
  std::string msg = "Hello, const correctness";
  DoTheThing(msg.c_str());
}

Вышеприведенный код не будет компилироваться, потому что msg.c_str() возвращает const char*. Чтобы получить этот код для компиляции, вам нужно будет сделать что-то вроде этого:

void MyFunction()
{
  std::string msg = "Hello, const correctness";
  DoTheThing(msg.begin());
}

... или даже хуже:

void MyFunction()
{
  std::string msg = "Hello, const correctness";
  DoTheThing(const_cast<char*>(msg.c_str()));
}

ни один из которых, возможно, "лучше", чем исходный код. Но поскольку DoTheThing() был написан некорректно, вы должны согнуть свой код вокруг него.

Ответ 4

Смысл в том, что вы гарантируете клиентам, вызывающим член функции const, что состояние объекта не изменится. Поэтому, когда вы говорите, что функция-член const, это означает, что вы не изменяете ни одной из переменных-членов объекта во время вызова функции.

Ответ 5

Очень необычно не хотеть менять какие-либо переменные-члены, но если это требуется вашему классу, то вы должны сделать все свои функции-члены const.

Однако вы, вероятно, хотите изменить хотя бы некоторые члены:

class A {
  private: 
    int val;
  public:
    A() : val(0) {}
    void Inc() { val++; }
    int GetVal() const { return val; };
};

Теперь, если я создаю два экземпляра A:

A a1;
const A a2;

Могу сказать:

a1.GetVal();
a2.GetVal();

но я могу только сказать:

a1.Inc();

пытается изменить значение постоянного объекта:

a2.Inc();

дает ошибку компиляции.

Ответ 6

Если это так, то следует ли его использовать везде, потому что я не хочу, чтобы ни один из переменных-членов не изменялся или не менялся каким-либо образом?

Ну, нет. Иногда вам нужны методы экземпляра для изменения членов. Например, любому методу набора, очевидно, нужно будет установить переменные, так что это не тот случай, когда вы должны указывать const везде. Но если ваше состояние объекта абсолютно неизменное, сначала подумайте, не может ли быть лучше вообще не иметь экземпляров (т.е. Статический класс), и если это не так, тогда сделайте все const.

Ответ 7

Ключевое слово const, используемое после метода, указывает, что этот метод не изменяет объект, на который он вызвал. Таким образом, этот метод можно вызвать в версии const объекта.