Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Композиция с кратностью многие-ко-многим ⇐ ПредыдущаяСтр 6 из 6
Отношение между объектами Book и Author более сложное, чем кажется на первый взгляд. С одной стороны, авторами одной и той же книги может быть несколько человек. С другой стороны - один автор мог участвовать в написании нескольких разных книг. Отношение с такой кратностью называют композицией многие-ко-многим. Это наиболее сложный вид композиции из всех возможных.
Отношение многие-ко-многим в большинстве случаев должно быть реализовано без ответственности за уничтожение. Такое отношение образует сложный граф связей между объектами, и понять используется объект где-либо еще достаточно сложно. Часто отношение многие-ко-многим представляет в предметной области некоторое логическое объединение нескольких сущностей в группу, нежели более сильное отношение владения, предполагающее ответственность за уничтожение. Обычно объекты, связанные отношением многие-ко-многим, создает и уничтожает какой-то третий объект, ответственный за хранение всех участвующих в такой модели объектов. В примере о книгах и авторах такую роль мог бы играть класс Library (библиотека).
Важной особенностью реализации такого вида композиции является обязательность использования форвардных деклараций в заголовочных файлах. Допустим, это ограничение нарушено, и программист использует директивы #include, чтобы связать определения классов друг с другом:
book.hpp
#include “author.hpp”
class Book { //... };
author.hpp
#include “book.hpp”
class Author { //... };
Попытка сборки проекта с таким подходом неизбежно приведет к зависанию либо фатальному сбою компилятора. Обрабатывая цепочку директив #include, препроцессор не сможет выбраться из бесконечной рекурсии, поскольку файлы включают друг друга.
Использование форвардных деклараций позволяет разорвать этот замкнутый круг. Директивы #include, свою очередь, размещают не в заголовочных файлах, а в файлах реализации классов. При этом, заголовочные файлы не могут использовать полные определения классов своих дочерних объектов. Соответственно, объявления всех полей и методов, как максимум, могут использовать эти классы только в виде указателя или ссылки, не обращаясь к содержимому. Работа с содержимым, при этом, в свободном доступе в CPP-файлов классов, поскольку они компилируются отдельно друг от друга и не образуют бесконечную рекурсию при компиляции.
Ниже представлен набросок примера с композицией многие-ко-многим, а полную версию можно посмотреть по ссылке в конце лекции.
author.hpp
#ifndef _AUTHOR_HPP_ #define _AUTHOR_HPP_
/*****************************************************************************/
#include <unordered_set> #include <memory> #include <functional> #include <string>
/*****************************************************************************/
// Форвардное объявление class Book;
/*****************************************************************************/
class Author {
/*-----------------------------------------------------------------*/
public:
/*-----------------------------------------------------------------*/
// …
// Метод, возвращающий количество книг автора int getBooksCount () const;
// Метод, выясняющий участвовал ли автор в написании указанной книги bool hasBook (Book const & _book) const;
// Метод, регистрирующий очередную книгу автора void addBook (Book const & _book);
// Метод, отменяющий регистрацию одной из книг автора void removeBook (Book const & _book);
// Метод очистки набора книг void clearBooks ();
// Метод обхода набора книг с применением указанного пользовательского действия void forEachBook (std::function< void (Book const &) > _action) const;
/*-----------------------------------------------------------------*/
private:
/*-----------------------------------------------------------------*/
// …
// Множество книг автора std::unordered_set< Book const * > m_books;
/*-----------------------------------------------------------------*/
};
/*****************************************************************************/
#endif // _AUTHOR_HPP_
author.cpp
#include “author.hpp” #include “book.hpp”
// Реализация методов автора...
library.hpp
#ifndef _LIBRARY_HPP_ #define _LIBRARY_HPP_
/*****************************************************************************/
#include <vector> #include <memory>
/*****************************************************************************/
// Форвардные объявления class Book; class Author;
/*****************************************************************************/
class Library {
/*-----------------------------------------------------------------*/
public:
/*-----------------------------------------------------------------*/
void addBook (std::unique_ptr< Book > _book);
//... другие полезные методы для работы с книгами
/*-----------------------------------------------------------------*/
void addAuthor (std::unique_ptr< Author > _authors);
//... другие полезные методы для работы с авторами
/*-----------------------------------------------------------------*/
private:
/*-----------------------------------------------------------------*/
// Книги библиотеки std::vector< std::unique_ptr< Book > > m_books;
// Авторы книг библиотеки std::vector< std::unique_ptr< Author > > m_authors;
/*-----------------------------------------------------------------*/
};
/*****************************************************************************/
#endif // _LIBRARY_HPP_
library.сpp
#include “library.hpp” #include “author.hpp” #include “book.hpp”
// Реализация методов библиотеки…
Полные примеры из лекции
https://github.com/zaychenko-sergei/oop-samples/tree/master/lec10
Выводы
В данной лекции были показаны типичные ошибки начинающих программистов при реализации отношения композиции между объектами на основе STL-контейнеров, а также выданы подробные рекомендации по удачному стилю реализации родительских классов. Рассматривались возможные варианты улучшения инкапсуляции при помощи контейнерных итераторов, а также средства std::function.
Позднее было введено понятие умных указателей, в частности, std::unique_ptr, и рассматривались способы их применения для упрощения реализации одиночной и множественной композиции с ответственностью за уничтожение дочерних объектов.
В завершении речь шла о вариантах оптимизации быстродействия композиции объектов за счет использования стандартных реализаций отображений и множеств, а также особенности применения композиции с кратностью многие-ко-многим, в частности, обязательность форвардных деклараций для разрыва компиляционных зависимостей.
|
||||||
Последнее изменение этой страницы: 2017-02-17; просмотров: 114; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.217.208.72 (0.015 с.) |