Идиомы и стили С++ | страница 11
Тем не менее, функций в классах остается достаточно много. Очевидно, что они группируются по своему назначению. Практически всегда есть группы, отвечающие за:
1. конструирование и инициализацию;
2. уничтожение и деактивацию;
3. сохранение и загрузку;
4. отображение;
5. обработку сообщений (событий).
Тут можно провести такую аналогию: если каждую функцию представить в виде одного провода, то их можно объединить в стандартный разъем: LPT, RS-232 или иной, и этот разъем будет обладать новыми, высшими свойствами, какими по отдельности провода не обладают; объединяя функции в цельные функциональные наборы мы так же получаем нечто новое. Присвоим этим наборам название, потом займемся реализацией. Термин возьмем у Microsoft. Необычно, нетривиально, метко, а главное, свежо: интерфейс. Элджер дает термин facet (грань), и suite (комплект, а не костюм). Где-то я еще видел термин sub-pointer, но этот термин применим только для одной реализации, но не отражает общей концепции. По счастью, именно об этой реализации мы и собираемся поговорить.
Итак, как же объединить функции-члены в наборы, опираясь на средства языка? Да просто: определить их в абстрактных базовых классах, а потом объединять их при помощи множественного наследования. Это вполне неплохая идея. Именно так создаются объекты на основе ATL: дается набор стандартных шаблонов для стандартных интерфейсов, потом объединяется при помощи множественного наследования. Указатели на интерфейсы Вы можете легко получать при помощи dynamic_cast‹T›, только на всякий случай обрабатывайте исключение (обратного преобразования так легко не сделать, к сожалению; вообще это проблема - преобразование базового класса в производный в случае множественного наследования; я собираюсь поговорить об этом позже, а в этом Шаге заклинаю Вас не использовать явного преобразования указателей, только dynamic_cast‹T› с перехватом исключения и проверкой на