Const-правильность для классов C ++ - PullRequest
2 голосов
/ 20 июля 2011
class SomeClass {
  public:
    void Render() const;

  private:
     mutable Cache m_some_cache;
};

Является ли класс выше const-правильным? Когда можно смело сказать «Эта операция не меняет внутреннего состояния экземпляра»?

В приведенном выше примере SomeClass - это то, что выводит материал на экран. Он использует кэш (например, объекты буфера OpenGL), чтобы ускорить обработку дальнейших вызовов. Таким образом, единственное, что изменяется внутри, это объект кеша. Я спрашиваю себя, принадлежит ли кеш уже внутреннему состоянию средства визуализации.

Пример очень минимален, но в моем реальном приложении это идет по пути со многими классами, то есть задействовано много вызовов Render (), и большинство из них выполняют только кэширование. Но некоторые также загружают ресурсы через загрузчик ресурсов - верно ли здесь предположение, что метод может быть константным, даже если он запрашивает у менеджера ресурсов загрузку ресурса?

Ответы [ 6 ]

6 голосов
/ 20 июля 2011

Когда мы говорим «внутреннее состояние не меняется», мы имеем в виду чисто логическую вещь. Это логическое решение о том, изменяет ли изменение m_some_cache состояние объекта. Константность - это логический вопрос. Итак, если вы считаете, что с точки зрения пользователя изменение m_some_cache не влияет на состояние объекта (в логическом смысле), тогда код является константно-правильным.

В вашем конкретном случае я считаю, что все в порядке.

4 голосов
/ 20 июля 2011

Думайте об этом так.Это совершенно верно:

void Type::print_self () const {
    std::cout << *this << std::endl;
}

Вы не изменяете сам объект, поэтому использование квалификатора const совершенно правильно.Этот метод модифицирует std::cout, но это не считается до const ness Type::print_self().

Тем не менее, mutable Cache выглядит мне противоречием в терминах, если толькоэтот элемент Cache используется только для локального хранения в Render.Если вы действительно используете его в качестве кеша, кажется немного сомнительным квалифицировать этот элемент как mutable.Используйте его как кеш (например, между вызовами Render, а не внутри вызова Render), и вы обманули и компилятор, и пользователя класса.

Редактировать
Согласно комментариям, сделанным ФП, метод Render действительно является графическим эквивалентом print_self().«Реальное» состояние объекта (предположительно, не показано для построения минимального рабочего примера) предположительно не изменяется при рендеринге.Обозначение Render как const является правильным решением.Если причина существования элемента данных Cache заключается в том, что он служит в качестве ускорения, позволяющего избежать затрат на его создание и уничтожение при каждом вызове Render, то нет ничего плохого в том, чтобы квалифицировать этот элемент Cache как mutable (чтонеобходимо, чтобы Render оставалось const).

3 голосов
/ 20 июля 2011

Когда можно смело сказать «Эта операция не меняет внутреннего состояния экземпляра»?

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

const касается только внутреннего состояния объекта. const -методы могут законно изменять внешнее состояние. Здесь на ум приходит аналогия с указателем: char * const p - это постоянный указатель, но он может изменить указанное значение. Так что ваш пример с менеджером ресурсов тоже кажется правильным.

2 голосов
/ 20 июля 2011

Вопрос, который нужно задать себе: «Изменит ли вызов функции Render измененное состояние или будущее поведение объекта в отношении пользователей?»

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

2 голосов
/ 20 июля 2011

Const-правильность о состоянии объекта, как видно снаружи.

Если все вызовы функций-членов продолжают возвращать один и тот же результат, состояние объекта логически одинаково.

2 голосов
/ 20 июля 2011

Как заметил @ildjarn, const-правильность относится к наблюдаемому, а не внутреннему состоянию объекта;Вот почему mutable полезен.

Опять же, если вы на самом деле визуализируете вещи, то наблюдаемое состояние объекта , представляющего экран , не может быть разумно const, ИМХО,поскольку он сломался бы, если бы позже вы добавили метод проверки, чтобы выяснить, что находится на экране / в буфере кадров.

Если SomeClass не отображает экран, то я ожидаю, что Render займетизменяемая ссылка, скажем, на Screen объект в качестве аргумента.По логике вещей, что-то должно измениться, даже если это не экземпляр SomeClass.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...