Шаг 9 - Множественные интерфейсные smart-указатели.
Шаг 9 - Множественные интерфейсные smart-указатели.
Вполне возможно, что Вы работаете с действительно крупным проектом, иерархия классов развилась до огромных размеров, а каждый класс (особенно внизу иерархии) обладает десятками или сотнями открытых функций. Конечно, неплохо задаться вопросом "Насколько разумно это?". Еще лучше, если этот вопрос задать до начала написания кода. Тогда можно вовремя почитать Гради Буча, установить на компьютер "Rational Rose" или сходную CASE-систему, и более чем тщательно спроектировать иерархию классов. К сожалению, вопросы объектного анализа и проектирования выходят далеко за рамки данного Шага и моих способностей. Но на всякий случай сообщу, что Microsoft серьезнейшим образом почистила библиотеку своих классов при выпуске версии для карманных компьютеров, и только в результате такой меры ЭТО стало вообще работать в каких-то разумных пределах и объемах; ошибки этапа моделирования вообще обходятся очень дорого впоследствии, особенно если система развивается.
Тем не менее, функций в классах остается достаточно много. Очевидно, что они группируются по своему назначению. Практически всегда есть группы, отвечающие за:
1. конструирование и инициализацию;
2. уничтожение и деактивацию;
3. сохранение и загрузку;
4. отображение;
5. обработку сообщений (событий).
Тут можно провести такую аналогию: если каждую функцию представить в виде одного провода, то их можно объединить в стандартный разъем: LPT, RS-232 или иной, и этот разъем будет обладать новыми, высшими свойствами, какими по отдельности провода не обладают; объединяя функции в цельные функциональные наборы мы так же получаем нечто новое. Присвоим этим наборам название, потом займемся реализацией. Термин возьмем у Microsoft. Необычно, нетривиально, метко, а главное, свежо: интерфейс. Элджер дает термин facet (грань), и suite (комплект, а не костюм). Где-то я еще видел термин sub-pointer, но этот термин применим только для одной реализации, но не отражает общей концепции. По счастью, именно об этой реализации мы и собираемся поговорить.
Итак, как же объединить функции-члены в наборы, опираясь на средства языка? Да просто: определить их в абстрактных базовых классах, а потом объединять их при помощи множественного наследования. Это вполне неплохая идея. Именно так создаются объекты на основе ATL: дается набор стандартных шаблонов для стандартных интерфейсов, потом объединяется при помощи множественного наследования. Указатели на интерфейсы Вы можете легко получать при помощи dynamic_cast‹T›, только на всякий случай обрабатывайте исключение (обратного преобразования так легко не сделать, к сожалению; вообще это проблема - преобразование базового класса в производный в случае множественного наследования; я собираюсь поговорить об этом позже, а в этом Шаге заклинаю Вас не использовать явного преобразования указателей, только dynamic_cast‹T› с перехватом исключения и проверкой на NULL). Но есть и недостатки, причем кроме чисто технических, на мой взгляд, есть еще один серьезный этап проектирования: множественное наследование в объектном анализе, применяется для реализации какого-то одного, редкого аспекта поведения, присущего разным несвязанным классам - "повадки" класса. Наследование от класса, склеенного из нескольких других, выведет проблему на новый уровень иерархии. Вывод - такая техника оправдана в листьях дерева классов, в самом низу иерархии.
Вариант номер два: использование нескольких умных указателей (далее я буду также называть smart-указателями или smart-pointer), каждый из которых предоставляет доступ к ограниченному, но функционально полному набору функций-членов (это называется полный минимальный интерфейс, то есть предоставляющий все необходимое, и ничего свыше совершенно необходимого). Вы уже знаете о них достаточно, и приводить подробный код будет теперь несколько несерьезно, разве что самые общие черты:
class Cоbject {
// функции набора 1
// функции набора 2
};
class Cfuncset1 {
private:
Cobject* obj;
public:
// функции набора 1
};
class Cfuncset2 {
private:
Cobject* obj;
public:
// функции набора 2
};
Обращаю внимание - использовать нужно именно простые умные указатели, или интерфейсные указатели из Шага 7, но не ведущие. Проблемы этого варианта очевидны, хотя бы чисто технические: преобразование интерфейсов и создание-удаление реального указываемого объекта. Smart-указатели тоже можно наследовать от абстрактных базовых классов, тогда Вы получите определенную жесткость своей конструкции. Сам указываемый объект может быть каким угодно. Склеили ли вы его через множественным наследование, или как единое целое он вообще не существует, а реализован как несколько жестко связанных объектов (бывает и такое) - клиентам это без разницы, если они все равно имеют к нему доступ через стандартные интерфейсы.
Подробности разберем в следующих Шагах, а сейчас я призываю Вас вспомнить, как в COM/DCOM сделано сохранение объектов: Вы имеете IStorage - умный указатель на объект "файл-хранилище", IPersist - умный указатель на объект, подлежащий записи, затем натурально сцепляете их, передавая указатель на IStorage в IPersist, и теперь Ваш объект просто выливается в свое хранилище, как молоко в глиняный кувшин. Объект может иметь любое количество иных интерфейсов, но наличие стандартного IPersist позволяет легко и красиво выполнить стандартную операцию.
Последнее: читайте Гради Буча! Учтите, что с первого раза он никогда (вообще!) не доходит. Только на второй или третий, не меньше, и то, если будете перемежать его с UML. Если Ваш проект действительно серьезный, то без грамотной модели он не существует. Этель Лилиан Войнич никогда бы не дописала свой роман "Овод", если бы с самого начала не задалась моделью: класс ‹солдат› обязательно должен иметь функцию ‹застрелить› экземпляр класса ‹мятежник›, а класс ‹офицер› во-первых, наследует от класса ‹солдат›, во-вторых, может отсортировать набор ‹солдат› в порядке возрастания - построить их на расстрел, в третьих - может и сам пристрелить врага при необходимости. Сильно подозреваю, что в этой модели функция ‹застрелить› является для ‹мятежника› дружественной. Выбирайте друзей правильно!
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
5. Множественные фоны
5. Множественные фоны Если бы два года назад меня спросили «Чего ты больше всего ждешь от CSS3?», я мог бы с энтузиазмом ответить: множественных фоновых изображений! В то время возможность показывать несколько фоновых изображений одного элемента казалась прекрасным
Аналоговые интерфейсные платы
Аналоговые интерфейсные платы Интерфейс PSTN, скорее всего (если не требуется обеспечение многоканальной линии или нет денег на то, чтобы каждый месяц менять телекоммуникационное оборудование), будет состоять из одной или более аналоговых схем, для каждой из которых
Цифровые интерфейсные платы
Цифровые интерфейсные платы Если требуется более 10 телефонных линий или обеспечение возможности подключения к цифровым линиям, используются платы T1 или E1[29]. Однако не стоит забывать, что ежемесячные расходы на обслуживание цифровых PSTN-линий варьируются в широких
Множественные интерфейсы и имена методов
Множественные интерфейсы и имена методов Множественное наследование является очень эффективной и простой технологией для реализации интерфейсов СОМ в классе C++. Это требует написания очень короткого явного кода, так как большая часть работы компилятора и компоновшика
Smart Fill (Интеллектуальная заливка)
Smart Fill (Интеллектуальная заливка) Наконец, четвертый фильтр пакета Image Doctor дает возможность не только избавляться от шума и мелких дефектов, но и устранять крупные объекты с фотографии, например, случайно попавшего в кадр прохожего, автомобиль, который портит пейзаж и т. д.
R.10.1 Множественные базовые классы
R.10.1 Множественные базовые классы Класс может быть производным по отношению к любому числу базовых классов. Приведем пример:class A {/*… */};class B {/*… */};class C {/*… */};class D: public A, public B, public C {/*… */};Использование более, чем одного прямого базового класса называется множественным
Шаг 7 - Интерфейсы. Интерфейсные указатели.
Шаг 7 - Интерфейсы. Интерфейсные указатели. Извините, тут лирическое отступление. Если хотите пропустить - нажмите PageDown.2001, март, 5 число. Вот уже седьмой шаг. Я ухлопал на эти шаги весь свой законный Курбан-Байрам, и не соблюдаю намаз. Одако не забываю добавлять коньяк в кофе,
Шаг 10 - Множественные интерфейсные указатели. Продолжение.
Шаг 10 - Множественные интерфейсные указатели. Продолжение. Humpty-Dumpty: "With a name of Your, You might be any shape, almost!" L. Carroll. Throw the looking glass. Сейчас мы поговорим о реализации, но до начала позвольте мне вернуться немного назад и добавить, что есть еще один неплохой способ организации множества
Множественные базовые классы
Множественные базовые классы Говоря о базовых классах, важно не забывать, что в C# каждый класс должен иметь в точности один непосредственный базовый класс. Таким образом, нельзя иметь тип с двумя или большим числом базовых классов (это называется множественным
Gigabyte G-Smart MW998
Gigabyte G-Smart MW998 Автор: Алексей Стародымов
Глава 5 Работа с ПО интерактивной доски SMART Board
Глава 5 Работа с ПО интерактивной доски SMART Board Самый быстрый способ запуска ПО — использование значка SMART Board (см. рис. 2.7) на панели задач, который символизирует работу Диспетчера устройств.ПО доски SMART Board позволяет работать в двух режимах:? режим ПК, включающий возможность
Принцип работы с инструментами SMART Board
Принцип работы с инструментами SMART Board Работая с доской, следует помнить, что на маркере нет правой кнопки. Так как данная доска резистивная, то на ней можно работать как маркером, так и пальцем руки. При этом вместо правой кнопки на каждом объекте или элементе будет
Программа Smart Flash Recovery
Программа Smart Flash Recovery Разработка компании Smart PC Solutions, Inc (http://www.smartpctools.com) – еще один пример простого решения, рассчитанного на пользователя с минимумом навыков.В раскрывающемся списке Select a drive (Выберите диск) выберите нужный носитель. Программа предлагает для выбора