18.3.4. Композиция объектов
18.3.4. Композиция объектов
* Есть две формы композиции объектов: композиция по значению, когда членом одного класса объявляется сам объект другого класса. Мы показывали это в исправленной реализации PeekbackStack;
* композиция по ссылке, когда членом одного класса является указатель или ссылка на объект другого класса.
Композиция по значению обеспечивает автоматическое управление временем жизни объекта и семантику копирования. Кроме того, прямой доступ к объекту оказывается более эффективным. А в каких случаях следует предпочесть композицию по ссылке?
Предположим, что мы решили с помощью композиции представить класс Endangered. Надо ли определить его объект непосредственно внутри ZooAnimal или сослаться на него с помощью указателя или ссылки? Сначала выясним, все ли объекты ZooAnimal обладают этой характеристикой, а если нет, то может ли она изменяться с течением времени (допустимо ли добавлять или удалять эту характеристику).
Если ответ на первый вопрос положительный, то, как правило, лучше применить композицию по значению. (Как правило, но не всегда, поскольку с точки зрения эффективности включение больших объектов не оптимально, особенно когда они часто копируются. В таких случаях композиция по ссылке позволит обойтись без ненужных копирований, если применять при этом подсчет ссылок и технику, называемую копированием при записи. Увеличение эффективности, правда, достигается за счет усложнения управления объектом. Обсуждение этой техники не вошло в наш вводный курс; тем, кому это интересно, рекомендуем прочитать книгу [KOENIG97], главы 6 и 7.)
Если же оказывается, что только некоторые объекты класса ZooAnimal обладают указанной характеристикой, то лучшим вариантом будет композиция по ссылке (скажем, в примере с зоопарком не имеет смысла включать в процветающие виды большой объект, описывающий виды вымирающие).
Поскольку объекта Endangered может и не существовать, то представлять его надо указателем, а не ссылкой. (Предполагается, что нулевой указатель не адресует объект. Ссылка же всегда должна именовать определенный объект. В разделе 3.6 это различие объяснялось более подробно.)
Если ответ на второй вопрос положительный, то необходимо задать функции, позволяющие вставить и удалить объект Endangered во время выполнения.
В нашем примере лишь небольшая часть всего множества животных в зоопарке находится под угрозой вымирания. Кроме того, по крайней мере теоретически, данная характеристика не является постоянной, и, допустим, в один прекрасный день это может перестать грозить панде.
class ZooAnimal {
public:
// ...
const Endangered* Endangered() const;
void addEndangered( Endangered* );
void removeEndangered();
// ...
protected:
Endangered *_endangered;
// ...
};
Если предполагается, что наше приложение будет работать на разных платформах, то полезно инкапсулировать всю платформенно-зависимую информацию в иерархию абстрактных классов, чтобы запрограммировать платформенно-независимый интерфейс. Например, для вывода объекта ZooAnimal на дисплей UNIX-машины и ПК, можно определить иерархию классов DisplayManager:
class DisplayManager { ... };
class DisplayUNIX : public DisplayManager { ... };
class DisplayPC : public DisplayManager { ... };
Наш класс ZooAnimal не является разновидностью класса DisplayManager, но содержит экземпляр последнего посредством композиции, а не наследования. Возникает вопрос: использовать композицию по значению или по ссылке?
Композиция по значению не может представить объект DisplayManager, с помощью которого можно будет адресовать либо объект DisplayUNIX, либо объект DisplayPC. Только ссылка или указатель на объект DisplayManager позволят нам полиморфно манипулировать его подтипами. Иначе говоря, объектно-ориентированное программирование поддерживается только композицией по ссылке (подробнее см. [LIPPMAN96a].)
* Теперь нужно решить, должен ли член класса ZooAnimal быть ссылкой или указателем на DisplayManager: член может быть объявлен ссылкой лишь в том случае, если при создании объекта ZooAnimal имеется реальный объект DisplayManager, который не будет изменяться по ходу выполнения программы;
* если применяется стратегия отложенного выделения памяти, когда память для объекта DisplayManager выделяется только при попытке вывести объект на дисплей, то объект следует представить указателем, инициализировав его значением 0;
* если мы хотим переключать режим вывода во время выполнения, то тоже должны представить объект указателем, который инициализирован нулем. Под переключением мы понимаем предоставление пользователю возможности выбрать один из подтипов DisplayManager в начале или в середине работы программы.
Конечно, маловероятно, что для каждого подобъекта ZooAnimal в нашем приложении будет нужен собственный подтип DisplayManager для отображения. Скорее всего мы ограничимся статическим членом в классе ZooAnimal, указывающим на объект DisplayManager.
Упражнение 18.6
Объясните, в каких случаях имеет место наследование типа, а в каких – наследование реализации:
(a) Queue : List // очередь : список
(b) EncryptedString : String // зашифрованная строка : строка
(c) Gif : FileFormat
(d) Circle : Point // окружность : точка
(e) Dqueue : Queue, List
(f) DrawableGeom : Geom, Canvas // рисуемая фигура : фигура, холст
Упражнение 18.7
Замените член IntArray в реализации PeekbackStack (см. раздел 18.3.1) на класс deque из стандартной библиотеки. Напишите небольшую программу для тестирования.
Упражнение 18.8
Сравните композицию по ссылке с композицией по значению, приведите примеры их использования.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Защита объектов ядра и приватных объектов
Защита объектов ядра и приватных объектов Многие объекты, такие как процессы, потоки или мьютексы, являются объектами ядра (kernel objects). Для получения и установки дескрипторов безопасности ядра используются функции GetKernelObjectsSecurity и SetKernelObjectsSecurity, аналогичные функциям защиты
Моникеры и композиция
Моникеры и композиция Моникеры часто составляются из других моникеров, чтобы с помощью текстового описания пути можно было осуществлять навигацию по иерархиям объектов. Чтобы обеспечить простую поддержку этого типа управления, в СОМ предусмотрена стандартная
Выделение объектов
Выделение объектов Только что созданный объект является выделенным. Понять, что объект является выделенным, очень просто: в окнах Тор (Вид сверху), Front (Вид спереди), Left (Вид слева) он всегда имеет контур белого цвета, в окне проекции Perspective (Перспективный вид) выделенный
Копирование объектов
Копирование объектов Представьте, что мы строим кровать, которая стоит на четырех ножках-опорах. Мы построили одну ножку, расположили ее в нужном месте, теперь необходимо построить еще одну. Каждый раз строить новую нерационально, особенно если это не просто ножка, а
Скрытие объектов
Скрытие объектов Чтобы облегчить управление сложными сценами, используют скрытие объектов. Это ускоряет отрисовку объектов в окнах проекций, в результате чего возрастает скорость работы. Скрытые объекты невидимы, и их нельзя выделить.Скрыть объекты можно несколькими
Композиция и стили в дизайне интерьеров
Композиция и стили в дизайне интерьеров Создание дизайна – непростое занятие. От идеи до готового интерьера – длинный и нелегкий путь. Главная задача, которую выполняет дизайнер, – разработка интерьера помещения, соответствующего индивидуальности хозяина, его
5. Композиция
5. Композиция Связь классов сущностей типа композиция, так же как и две предыдущие, не принадлежит к виду рекурсивной связи.Композиция (или, как ее еще иногда называют, композитная агрегация) – это взаимосвязь одного родительского класса сущностей с несколькими дочерними
18.3.1. Наследование и композиция
18.3.1. Наследование и композиция Реализация класса PeekbackStack с помощью закрытого наследования от IntArray работает, но необходимо ли это? Помогло ли нам наследование в данном случае? Нет.Открытое наследование – это мощный механизм для поддержки отношения "ЯВЛЯЕТСЯ". Однако
Растягивание объектов
Растягивание объектов Команда STRETCH осуществляет растягивание объектов, сохраняя при этом связь с остальными частями рисунка. Вызывается она из падающего меню Modify ? Stretch или щелчком на пиктограмме Stretch на панели инструментов Modify.Запросы команды STRETCH:Select objects to stretch by
Композиция
Композиция По статистике, самый ненавистный предмет у учеников и студентов музыкальных учебных заведений – сольфеджио. Самый ненавистный комплекс упражнений в школе танца – у станка. А в рисунке, фотографии и прочих «изобразительных» предметах самым сложным моментом
5.3. Композиция кадра
5.3. Композиция кадра Громадная щука, сфотографированная рыболовом, может выглядеть грозным чудовищем, если заснять ее, бьющуюся в сетях, или безобидным полуфабрикатом для ухи, брошенным в корзину или ведро. Попробуйте сфотографировать человека в свете, льющемся из
Композиция
Композиция В большинстве случаев пейзажу традиционно свойственна горизонтальная компоновка кадра, но это вовсе не обязательно. Все зависит от выбранного вами сюжета: если главный элемент расположен вертикально, стоит, конечно, развернуть камеру.Первое правило —
Композиция
Композиция Необходимо определить, что именно вы хотите подчеркнуть, выделить в фотографии. Подумайте, нужно ли усилить резкость, контраст, чтобы показать на фото мужественное лицо, изношенное временем, дождем и жарой старое заброшенное судно, или, наоборот, смягчить
Композиция
Композиция Выстраивайте кадр с учетом скорости и направления движения, оставляя перед движущимся объектом свободное пространство. Объект не должен останавливаться перед «стенкой» – граница кадра создает эффект остановки движения.Чтобы добиться эффекта движения,