Re[4]: const - когда быть, когда не быть
От: Дмитро  
Дата: 24.04.03 03:16
Оценка: 10 (1)
Здравствуйте, Аноним, Вы писали:

А>Бездумное программирование вообще создаёт много неприятностей


Не стоит обобщать мои слова доводя их до банальности. Далее о тексту я привожу пример и разъясняю свои точку зрения.

А>Напротив, очень даже странно, функция doSomething() ни входных, ни выходных параметров не имеет, возвращаемого значения тоже нет и объект не меняет. Что же она должна делать? (Только писать в std::cout "Hello world!"?! )

А>Короче "const" тут сразу под большим вопросом.

Это абстрактный пример. Метод A::doSomething не меняет значения членов-данных класса A -- вот что важно . Как он это делает (т.е. не меняет члены-данные), печатает ли "Hello world" или еще что-то, не имеет принципиального значения. Наверное, чтобы пример был более убедительным, он должен был бы, как минимум, что-то возвращать. С этим я согласен.

То, что я хотел сказать, так это то, что бывают такие ситуации, когда методы в классе (независимо от количества и типов параметров и типа возвращаемого значения) не меняют члены-данные и при этом выполняют полезную работу.

Д>Далее пишется отпределенное количество кода, ... В общем, хорошо.


Д>И вдруг, нам понадобилось создать класс B унаследованный от A и переопределить в нем doSomething. И тут оказывается, что B::doSomething меняет члены данных класса B, поэтому не может быть константным!


А>А мне кажется странным, что у нескольких классов до этого функция doSomething была константной, а у нового класса эта функция оказывается неконстантной. Может быть новый класс делает в doSomething чего не должен делать? А может...


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

Д>Можно воспользоваться последними достижениями прогрессивного человечества -- модификатором mutable и объявить с его помощью все члены-данные, которые меняются в методе B::doSomething...

А>Логичнее было бы воспользоваться другим достиженим прогрессивного человечества — const_cast.

Признаюсь, забыл про const_cast. А вспомнил, почему-то, только про mutable. Способов избавиться от нежелательной константности можно придумать много, но сам факт появления этой нежелательной константности говорит о недальновидности проявленной на этапе проектирования интерфейсов классов.

А>А еще логичнее перепроектировать новый класс или подвергнуть рефакторингу всю иерархию.


Этот вариант я рассматривал. Лично я склоняюсь более к нему. Однако он имеет свои недостатки -- нужно что-то переделывать, переписывать, исправлять. Можно было этого как-то избежать? Да, не сделали бы метод константным -- не надо было бы ничего переписывать.


Д>Исходя из своего опыта, могу сказать, что в большинстве случаев:


Д>1. const никогда не следует использовать в объявлении методов интерфейсных классов.

А>Не согласен у методов аля "Get", модификатор const должен быть в подавляющем большинстве случаев.

Методы аля "Get" могут возвращать данные, которые могут и не храниться непостредственно в объекте. Они могут читать из файла, делать запросы по сети, устанавливать и разрывать при этом соединения, кешировать эти данные наконец. При этом, возможно, что-то в классе и поменяется. Но пользователю класса нужно только получить эти данные. И его не должно беспокоить каким образом они были получены. Его не должно беспокоить, поменялся ли какой-нибудь внутренний указатель или дескриптор сокета, к которому он все равно доступа, может быть, никогда и не получит. Как получить эти данные -- забота разработчика класса, и я считаю, что он, в свою очередь, не должен заботиться о том, как избавиться от нежелательной константности. Кстати, ты не рискнул сказать "во всех случаях", ты сказал мягче "в подавляющем большинстве случаев". Полагаю, ты сталкивался с теми случаями, когда все же не нужно было делать метод константным.

Д>Модификатор const в данном случае навязывает разработчику классов (наследующихся от заданных интерфейсных) некое внутреннее представление и, как следствие, нарушает инкапсуляцию.

А>Не совсем понял.
А>Во-первых сам интерфейс есть некое навязывание. (Не хочешь навязывания, есть замечательный () void *, а также возможность сериализовать объект в поток байт )
А>Во-вторых каким это образом const разрушает инкапсуляцию!?

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


Те четыре пункта, которые я приводил в своем посте никак не претендуют на полноту, не претендуют на то, чтобы быть базисом (чтобы одно не являлось частным случаем другого). Это одни из тех эмпирических правил, которыми я пользуюсь бессознательно. Я их придумал и сформулировал пока писал пост. Причем первый придумал сразу, а остальные додумывал как противовес первому. Эти четыре пункта не котегоричны. Их не стоит передергивать и поправлять "нет такого правила!" или "это частный случай!". Конечно, я ведь не ставил себе целью составить правила на все случаи жизни. В любом случае, решение будет принимать разработчик в каждом конкретном случае. А эти четыре пункта следует воспринимать скорее как совет, как мой ответ на вопрос "const — когда быть, когда не быть?" с уклоном в сторону "когда же ему все-таки не быть.".

А>P.S. Есть книги, которые посвящены подобным вопросам. ("Что и когда стоит или не стоит использовать в C++") Может стоит заглянуть в раздел сайта посвященным книгам по C++?


Давай конкретно, какие книги и ссылки ты бы мне советовал прочитать?

--
Дмитрий
--
Дмитрий
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.