Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Композиция объектов. Иерархии целое-часть. Структура простейшей композиции по значению в памяти. Ответственность за уничтожение объектов при композиции




КОМПОЗИЦИЯ (или агрегирование, включение) - простейший способ создания новых более сложных классов путем объединения нескольких объектов существующих классов в единое целое.

Между классом верхнего и нижнего уровня обычно присутствует отношение "целое-часть". Ниже приведен простейший пример композиции — объект двигатель (Engine) является частью объекта автомобиль (Car):

 

С точки зрения памяти, поля дочернего объекта размещаются внутри родительского объекта целиком. К слову, объект std::string m_model также является дочерним объектом, и размещается полностью в родительском объекте Car, с той разницей, что модель - является объектом-значением, а двигатель - объектом-сущностью.

 

В одном объекте может быть несколько дочерних объектов - одного или разных типов. Дочерние объекты могут выделяться как вместе с родительским, так и динамически. При этом родительский класс может быть ответственен либо не ответственен за уничтожение дочерних объектов в зависимости от ситуации. Если доступ к объекту имеет только один класс, то он является ответственным за уничтожение, если же кто-то ещё имеет доступ, то тогда не является ответственным за уничтожение.

Ссылочная композиция. Разрываемая композиция. Кратность композиции. Одиночная, множественная и недетерминированная кратность.

Ссылочная композиция.

Некоторые виды композиции не предполагают ответственности на уничтожение д

дочернего объекта. Такая связь скорее является логическим объединением в группу, нежели жестким отношением целое-часть. Для дочерних объектов в логических объединениях свойственно вхождение сразу в несколько родительских объектов. В таком случае за уничтожение дочернего объекта отвечает кто-либо другой, а не родительский объект.

Если такая связь между объектами является постоянной, то, как правило, дочерний объект хранится по ссылке либо константной ссылке, которая передается в родительский объект при конструировании. Обычно, таким видам объектов не свойственно копирование и присвоение, и эти операции имеет смысл в явном виде запретить.

Ниже представлено логическое объединение между орудием (Weapon) и его типом, или моделью (WeaponType). Каждый экземпляр класса Weapon получает ссылку на тип орудия WeaponType в конструкторе, и эта ссылка сохраняется до конца жизни объекта орудия. Предполагается, что тип орудия просуществует дольше любого из орудий. Это ограничение должно обеспечиваться внешним по отношению к рассматриваемым классам кодом.

Разрываемая композиция

Некоторые виды отношений целое-часть не являются постоянными. Дочерний объект может прикрепляться к родительскому в течение его жизни, а при необходимости — отцепляться и прикрепляться к другому родительскому объекту. Такое поведение свойственно отношениям, в которых дочерний объект имеет существенную долю обязанностей по сравнению с родительским объектом, и имеется практический смысл в его существовании вне родительского либо с другим родителем. При этом родительский объект по-прежнему может отвечать за уничтожение дочернего.

Ниже представлен класс, моделирующий вертолет (Helicopter). Вертолет имеет уникальный числовой номер. Вертолет находится в конкретный момент времени по конкретным координатам и его нос направлен под конкретным углом относительно осей. На вертолет может быть установлено необязательное к наличию орудие (объект Weapon). При наличии орудия, вертолет может производить выстрелы, в противном случае — только летать.

С точки зрения хранения данных в памяти, единственным способом для реализации такой необязательной связи между объектами является хранение указателя на дочерний объект в памяти родительского. Указатель будет адресовать конкретный дочерний объект, если связь установлена. При отсутствии связи значение указателя будет равно nullptr.

Связь между объектами Helicopter и Weapon не является обязательной. Она может устанавливаться внешне через вызов метода installWeapon, а затем разрываться через вызов deinstallWeapon. Во избежание ошибок объект-вертолет должен проверять, что может быть установлено только одно орудие, а также гарантировать, что снять орудие можно только после его установки. Если орудие прикреплено к вертолету на момент его уничтожения, орудие уничтожается вместе с ним.

Кратность композиции.

Одиночная кратность (связь один-ко-одному) Car-Engine

Множественная кратность(один-ко-многим) (HelicopterEscadrille-Helicopter).

Недетерминированная кратность (многие-ко-многим) (HelicopterPilot-MilitaryMission).

 

 

23. Применение контейнера std::vector для композиции с недетерминированной кратностью. Композиция объектов-значений и объектов-сущностей.

 

Вектор является одним из классов-контейнеров стандартной библиотеки шаблонов (STL - Standard Template Library). STL-контейнеры, такие как вектор, представляют собой реализацию классических структур данных, ранее рассмотренных в обеспечивающей дисциплине. Подобные мощные утилитарные классы для классических структур имеются во всех современных языках программирования, и С++ не является исключением.

 

Простейшие типовые операции, характерные векторам, доступны через методы класса std::vector, среди них такие массово используемые во многих программах:

● size - возвращает число хранимых элементов;

● empty - выясняет пуст ли вектор;

● clear - очищает вектор;

● push_back - добавляет новый элемент в конец вектора

● pop_back - удаляет элемент с конца вектора;

● оператор индексной выборки [] - доступ к элементу с конкретным индексом без проверки;

● at - доступ к элементу с конкретным индексом с проверкой на выход за границу;

● insert - вставляет элемент в указанную конкретную позицию (с автоматическим сдвигом);

● erase - удаляет элемент из указанной конкретной позиции (с автоматическим сдвигом)

 

Реализация вектора из стандартной библиотеки полностью берет на себя ответственность за управление необходимой динамической памятью. В ней определены нужные конструкторы, операторы и деструктор, автоматически выделяющие и освобождающие память внутренних данных без необходимости вмешательства со стороны программиста.

 

Помимо того, что такая реализация предоставляет решение основной проблемы - динамическое изменение количества фиксируемых объектов - благодаря использованию вектора удается достичь существенных упрощений реализации:

● нет необходимости в передаче и извлечении максимального числа объектов;

● исчезает необходимость в явном деструкторе, поскольку деструктор вектора, который освободит выделенный блок памяти, будет автоматически вызван из генерируемого компилятором автоматического деструктора класса;

● исчезает необходимость в запрещении конструктора копий, поскольку реализация класса std::vector обладает функциональностью корректного копирования своего содержимого, и никаких "висячих" указателей в автоматическом конструкторе копий не возникнет;

● вектору также можно доверить проверку индексов при доступе к конкретным объектам.

 

 

Основная отличительная особенность любых объектов-значений - возможность свободного копирования и присвоение подобно встроенным типам. Наличие у объектов-точек такой возможности позволило легко поместить их в вектор.

 

Часто существует необходимость во множественной композиции объектов-сущностей, которые, как правило, не предполагают или даже полностью запрещают копирование, поскольку двух одинаковых объектов-сущностей в программе одновременно существовать не должно. Из невозможности копирования объектов вытекает невозможность помещения объектов в вектор. Также в вектор нельзя помещать ссылки на объекты, поскольку ссылка не является копируемой в принципе. Очевидно, в таком случае остается лишь одно решение - вместо объектов или ссылок на объекты в вектор следует поместить указатели на объекты. Указатели могут копироваться и имеют значение по умолчанию не зависимо от типа данного (nullptr).

 

Отдельного внимания требуют случаи, когда родительский объект является ответственным за уничтожение дочерних объектов-сущностей. Помещение указателя на некоторый объект в вектор не является причиной для его автоматического уничтожения (вектор не может догадаться о намерении программиста), и в таких случаях следует позаботиться об уничтожении вручную.

 

Как видно из приведенной реализации, внедрение векторов вместо массивов позволило также достичь ряда заметных упрощений, среди которых следующие:

● полностью исчезла какая-либо необходимость в собственном конструкторе, т.к. более нет потребности передавать максимальный размер эскадрильи, аналогично, был убран метод getMaxUnitsCount, смысл которого теперь утерян;

● реализация больше не хранит нулевые указатели для сбитых или выведенных из состава эскадрильи вертолетов, соответственно нет нужды в методе findFreeUnitPosition;

● метод getHelicopter возвращает ссылку на объект-вертолет вместо указателя, поскольку нулевых указателей внутри вектора теперь не хранится;

● аналогично примерам о журнале полета и истории приземлений вертолетов на площадке, проверку индексов при доступе берет на себя вектор;

● реализация метода getJoinedUnitsCount упрощается до запроса количества размещенных элементов внутреннего вектора;

● при добавлении вертолета в эскадрилью его адрес просто помещается в конец вектора;

● при исключении вертолета из состава эскадрильи используется готовый алгоритм метода erase с автоматическим сдвигом, что было возможно в предыдущей реализации, но не привлекало громоздкостью ручного кодирования в явном виде.

 

 





Поделиться с друзьями:


Дата добавления: 2016-07-29; Мы поможем в написании ваших работ!; просмотров: 696 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Свобода ничего не стоит, если она не включает в себя свободу ошибаться. © Махатма Ганди
==> читать все изречения...

4453 - | 4147 -


© 2015-2026 lektsii.org - Контакты - Последнее добавление

Ген: 0.008 с.