Должны ли функции-члены быть «константными», если они влияют на логическое состояние, но не на побитовое состояние? - PullRequest
8 голосов
/ 06 марта 2011

Я пишу класс, который упаковывает устаревший C API, который управляет аппаратным устройством. В упрощенном примере у меня может быть что-то вроде:

class device
{
public:
    void set_request(int data) { legacy_set_req(p_device, data); }
    int get_response() const   { return legacy_get_rsp(p_device); }
private:
    device_handle_t *const p_device;
};

Сам класс не имеет побитового состояния; поэтому я мог бы объявить set_request() как const, и компилятор был бы доволен этим. Однако с семантической точки зрения, будет ли это правильным подходом, учитывая, что он влияет на наблюдаемое поведение объекта? (т.е. инкапсулированное аппаратное устройство очень имеет состояние.)

Ответы [ 4 ]

18 голосов
/ 06 марта 2011

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

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

9 голосов
/ 06 марта 2011

Если он меняет состояние, обычно не будет const.Тот факт, что рассматриваемое состояние принадлежит удаленно (т. Е. В управляемом устройстве), не меняет этого.

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

Полезный тест:

может кодировать только с помощью const доступа к экземпляру устройства, мешать работе кода с не-const доступом

В принципе, const доступ означает, что вы фактически являетесь наблюдателем. Здесь выглядит так, как если бы код, вызывающий set_request(...) в момент времени T1, тогда get_response() в момент времени T3 был бы серьезно испорчен, если бы некоторый предполагаемый наблюдатель вызвал set_request() с другими параметрами в момент времени T2. По этой причине set_request(...) не должен быть доступен для наблюдателей - он должен быть не const.

(В тесте есть предостережения - например, если const «наблюдатель» нуждается в блокировке, он, очевидно, может повлиять на использование не const из другого потока с точки зрения синхронизации, но не должен делать это с функциональной точки зрения. - но совершенно очевидно, как учесть это в вашем анализе).

2 голосов
/ 06 марта 2011

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

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