2012-03-21 2 views
2

Представьте, что у меня есть класс «Окно» с функцией «показать», что приводит к тому, что основное окно становится видимым на экране.Функция-член-член, когда операция имеет явные побочные эффекты

Поскольку я вызываю базовый API окон для этого, я никоим образом не изменяю состояние моего объекта «Window», но, тем не менее, явное изменение состояния моего окна происходит из-за вызова это (окно появляется на экране и возможность быть взаимодействовали с пользователями)

так что я должен объявить свою функцию -

void Window::show() const; 

, потому что, насколько объект Window касается этой функции Безразлично» t изменить любое состояние и, следовательно, можно вызвать объекты «const Window». Но почему-то это не кажется правильным, поскольку вызов этой функции явно в каком-то смысле изменяет состояние объекта.

+1

Согласен. Даже если это можно технически сделать, было бы трудно утверждать, что это не нарушает понятие «константы» для этого. –

+0

Думая об этом, было бы полезно иметь функции, которые имеют функции «const Window &», зная, что эти функции могут смотреть только на окно, а не изменять его вообще. – jcoder

ответ

6

Возможно, вы сталкиваетесь с тем, что C++ не имеет понятия о чистоте, то есть имеет ли функция побочные эффекты или нет. const функции-члены выполняют только обещание, что состояние самого объекта не будет изменено.

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

Таким образом, в то время как show() может кстати быть маркированы const, логически следует не быть. Если бы это было действительно const, тогда вы ожидали бы такую ​​функцию, как is_visible(), чтобы вернуть такое же значение как до, так и после звонка до show(), и, очевидно, это не так.

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

+0

Хмм хороший момент. – jcoder

+1

Многое зависит от того, что вы понимаете абстракцией «окна». Я думаю, вы можете аргументировать вопрос в обоих направлениях. Точно так же вы можете спорить с любым 'const', по любой функции; функция, подобная 'is_visible()', если она разрешает запрос диспетчеру окон, может изменить состояние без вызова какой-либо функции-члена. –

+1

@JamesKanze: Есть все еще разница между функциями, которые извлекают значение, подлежащее изменению ('get_x()'), и те, которые фактически изменяют значение ('show()'). В игре, например, вы хотите, чтобы 'get_x()' возвращал компонент 'x' объекта * в текущий момент *. Изменения в 'x' со временем происходят из других источников, и вы просто наблюдаете их. –

2

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

Редактировать: Дайте этому еще подумать. Возможно, ваш объект содержит дескриптор окна ОС, и этот дескриптор можно передать в функции ОС. У дескриптора на самом деле нет понятия constness, поэтому это несоответствие импеданса с C++, но функция, с которой вы его передаете, будет либо запрашивать свойство window (const), либо каким-либо образом модифицировать окно (не const). Было бы полезно, чтобы ваш объект применял концепцию Constance, даже если ОС не работает.

+0

Я понимаю проблемы языка C++, это скорее вопрос о том, что такое хороший дизайн. Возможно, единственный ответ: «Это зависит ...» – jcoder

4

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

4

Это классический логический const по сравнению с поразрядным вопросом.Это было , когда я учился на C++ (начало 1990-х годов), но с , тогда, я думаю, есть консенсус в пользу логического const: если логическое состояние объекта меняется, тогда функция не должна быть const (даже если компилятор позволит const), и если логическое состояние не меняется, то функция должна быть const (даже если вы потребность mutable или откинуть сопзЬ делать, например, кэшированный результат вычисление).

В конкретном случае Window::show трудно сказать. Является ли факт , что окно отображается частью своего «логического состояния» или нет.

0

Обычно такая ситуация:

  • Для каждого окна API существует более одного C++ объекта окна.

  • Объект C++ window не может быть скопирован (в том числе, что он не является клонированным).

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

Однако, как только одно или оба ограничения удаляются, оно становится бесполезным и бессмысленным упражнением. Рассмотрим, например, удаление второго ограничения, что делает объекты C++ скопируемыми. Возможно, это имеет смысл, рассматривая объекты C++ почти как shared_ptr экземпляры (за исключением уничтожения).

Но любой const shared_ptr может быть скопирован на номер const, поэтому любые вызовы без const могут быть вызваны. Например, shared_ptr::get - это метод const, так что он может быть вызван на объект const shared_ptr. Но его результат равен T*, то есть нет const распространения на результат, потому что даже если он был T const*, он бы не ограничивал клиентский код: клиентский код мог просто скопировать const shared_ptr на номер const, а затем позвонить get на не const экземпляр.

Тем не менее, с обеими gurantees выше в месте с тем, что const (или в случае отсутствие const) может использоваться в возможно полезном способе ограничить операции на упомянутое окне API, не означает, что он это обязательно хорошая идея.

В частности, объекты, представляющие окна, обычно являются приемниками событий, и, по моему опыту, события не очень хорошо сочетаются с const.

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

+0

Я согласен с тем, что не копируем, но вы можете передать ссылку на константу для функции, которая требуется для Например, можно получить ширину и высоту окна? – jcoder

Смежные вопросы