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

20

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

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

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

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

    
задан ggg 28.01.2010 в 20:46
источник
  • Если переменные-члены никогда не меняются, почему у вас есть переменные-члены? –  Chris Farmer 28.01.2010 в 20:49
  • Потому что он хочет, чтобы класс неизменен? Это не является необоснованным. –  Jan 28 '10 at 19:50 28.01.2010 в 20:50
  • Я на самом деле не человек на языке c ++, поэтому это был скорее вопрос интереса, чем вопрос «gotcha». Почему бы вам просто не объявить всех своих членов «const», если вы хотите, чтобы это было действительно неизменным? Или вы оба объявляете члены как const и методы как const? –  Chris Farmer 28.01.2010 в 20:52
  • Я бы просто объявил методы const, но вы могли бы сделать и то, и другое. На самом деле тема не поддается описанию в комментарии. –  28.01.2010 в 20:57
  • @dreamlax: Я согласен. –  GManNickG 28.01.2010 в 21:29

7 ответов

32

Метод 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, прежде чем отправиться на эту территорию.

    
ответ дан R Samuel Klatchko 28.01.2010 в 20:50
источник
  • Если один, то для безопасности, источник const для всех методов, которые, как ожидается, не изменят состояние объекта? (например, геттеры) –  gen 18.07.2016 в 21:47
  • Для корректности состязания, да. –  U007D 15.02.2017 в 23:52
5

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

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

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() было написано некорректно, вы должны согнуть свой код вокруг него.

    
ответ дан John Dibling 29.01.2010 в 00:00
источник
4

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

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

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

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

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

    
ответ дан Ben Supnik 28.01.2010 в 21:00
источник
3

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

    
ответ дан mikelong 28.01.2010 в 20:49
источник
  • Это не совсем так - наблюдаемое поведение не изменяется, но данные члена могут быть отмечены как изменяемые. Это позволяет, например, кэшировать однократно рассчитанные результаты. –  David Thornley 28.01.2010 в 21:01
  • Это еще хуже. Если у вас есть указатель, указывающий на некоторые данные, const за функцией-членом гарантирует, что указатель не будет изменен, а не данные, на которые он указывает. Часто, однако, данные считаются частью состояния объекта. Итак, на самом деле, const не позволяет функции-члену изменять данные элемента объекта, а не все его состояние. Он обеспечивает бит-мудрую константу, а не логическую константу. –  sbi 28.01.2010 в 21:15
  • Действительно, он только обеспечивает побиточную константу, и все ставки отключены, когда вы устанавливаете элемент mutable. Это только на самом деле намек на компилятор, г-н Klatchko имеет лучшее объяснение выше. –  mikelong 29.01.2010 в 15:13
3

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

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

    
ответ дан anon 28.01.2010 в 20:49
источник
  • Методы, не изменяющие внешнее состояние, чаще встречаются в декларативном программировании - по общему признанию, это не самая простая вещь на C ++ на данный момент. Но в настоящее время существуют более плавные библиотеки библиотек C ++ (например, Ranges v3), которые сделают это более практичным в будущем. –  U007D 15.02.2017 в 23:54
2
  

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

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

    
ответ дан John Feminella 28.01.2010 в 20:49
источник
2

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

    
ответ дан Mathieu Pagé 28.01.2010 в 20:51
источник