Подтвердить что ты не робот

Что может изменить метод "const"?

Методы С++ позволяют квалификатору const указывать, что этот метод не изменен. Но что это значит? Например. если переменные экземпляра являются указателями, означает ли это, что указатели не изменяются или также не изменяется память, на которую они указывают?

Конкретно, вот минимальный примерный класс

class myclass {
  int * data;

  myclass() {
    data = new int[10];
  }

  ~myclass() {
    delete [] data;
  }

  void set(const int index) const {
    data[index] = 1;
  }
};

Соответствует ли метод set как const? Он не меняет переменную-член data, но она действительно меняет содержимое массива.

4b9b3361

Ответ 1

Вкратце, это означает, что тип this является const T * внутри const-функций-членов, где T - ваш класс, а в неквалифицированных функциях - T *.

Ваш метод set не изменяет data, поэтому его можно квалифицировать как const. Другими словами, myclass::data получает доступ как this->data и имеет тип int * const.

Ответ 2

Что может изменить метод 'const'?

Без явной отбрасывания константы метод const может измениться:

  • mutable, и
  • любые данные, к которым у класса нет доступа const, независимо от того, доступны ли эти данные:
    • через переменные-члены, которые являются указателями или ссылками,
    • через указатели или ссылки, переданные как параметры функции,
    • через указатели или ссылки, возвращаемые функциями,
    • непосредственно в пространстве имен или классе (для статики), содержащем его.

Для членов типа class/struct/union он полагается на константу своих функций-членов, чтобы определить, какие операции должны быть разрешены. (Он также может изменять любые неконстантные локальные переменные и параметры по значению, но я знаю, что не то, что вас интересует).

Он может вызывать другие методы const, которые будут иметь эти же возможности и ограничения.

Eg. если переменные экземпляра являются указателями, означает ли это, что указатели не изменяются или также не изменяется память, на которую они указывают?

Это означает, что указатели не могут быть (легко/случайно) изменены. Это не означает, что память с заостренной памятью не может быть изменена.

То, что вы наткнулись, - это логическая некорректность функции const, которая изменяет данные с привязкой к объекту или ссылки, концептуально принадлежащие объекту. Как вы нашли, компилятор не применяет правильность const, которую вы можете ожидать или ожидаете здесь. Это немного опасно, но означает, что константа не требуется явно удалять для указателей/ссылок на другие объекты, которые могут быть изменены как побочный эффект функции const. Например, объект регистрации. (Как правило, такие объекты не логически "принадлежат" объекту, функция которого const работает на них.) Ключевым моментом является то, что компилятор не может достоверно различать тип логического права собственности на объект, связанный с данными, поэтому он должен угадать, так или иначе, и позволить программисту либо переопределить, либо не защищаться с помощью const -ness. С++ отказывается от защиты.

Интересно, что я слышал, что язык Walter Bright D переворачивает это значение по умолчанию, делая указательные данные const по умолчанию в const. Это кажется мне более безопасным, хотя трудно представить, как часто в конечном итоге нужно явно отбросить постоянство, чтобы разрешить нежелательные побочные эффекты, и будет ли это удовлетворительно точным или досадно подробным.

Ответ 3

В этом вопросе есть два аспекта:

  • Что означает const для компилятора?
  • Как применяется const, когда он не может быть проверен компилятором?

Вопрос 1

Первое довольно просто. Компилятор проверяет, что ни один элемент данных не изменяется (если только они не определены как mutable). Он проверяет это рекурсивно: для любых пользовательских типов он проверяет, что не вызываются никакие неконстантные методы. Для встроенных типов он проверяет, что они не назначены.

Преобразование для указателей составляет от T* до T*const (const указатель), а не const T* (указатель на const). Это означает, что компилятор не подтверждает, что указанный объект не изменяется. Очевидно, это приводит к вопросу 2.

Вопрос 2

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

Ответ 4

const в основном предотвращает изменение значений элементов экземпляра класса класса внутри функции. Это полезно для более четкого интерфейса, но, например, создает ограничения при использовании наследования. Это иногда немного обманывает (или много на самом деле), как в примере, который вы опубликовали.

const будет наиболее подходящим для функций Get, где очевидно, что вызывающий объект читает значение и не имеет намерений изменять состояние объекта. В этом случае вы хотели бы ограничить унаследованные реализации, а также придерживаться const ness, чтобы избежать путаницы и скрытых ошибок при использовании полиморфизма.

Например

class A{
     int i;
   public:
     virtual int GetI() {return i;};
}

class B : public A{
   public:
     int GetI() { i = i*2; return i;}; // undesirable
}

изменение A на:

virtual int GetI() const {return i;};

решает проблему.

Ответ 5

const при применении к методу означает:

Это означает, что метод state объекта не будет изменен методом.
Это означает, что любые члены, которые являются частью состояния объектов, не могут быть изменены, а также не могут быть вызваны любые функции, которые также не будут const.

Как это относится к указателям. Это означает, что указатель (если он является частью состояния) не может быть изменен. Но объект, на который указывает указатель, является частью другого объекта, что означает, что вы можете вызывать метод non cost для этого объекта (поскольку он не является частью состояния этого объекта).