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

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

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

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

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

7 ответов

Решение

Метод 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, но здесь есть более широкая картина - и в этом идея правильности const.

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

bool DoTheThing(char* message);

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

Практическая ценность также состоит в том, чтобы сделать ваши функции правильными. А именно, в зависимости от контекста вызова, вы не сможете вызывать 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() написан некорректно, вы должны обернуть код вокруг него.

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

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

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

Обычно вы хотите объявить все не мутирующие нестатические методы класса как const. Это позволяет вызывающему коду использовать указатель const в указателях и помогает отлавливать ошибки.

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

Это означает, что вы гарантируете клиентам, вызывающим член функции 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();

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

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

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

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

Другие вопросы по тегам