Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Рекомендованный стиль интерфейса родительских классовСодержание книги
Поиск на нашем сайте
В целом, отношение композиции с недетерминированной кратностью один-ко-многим, подобное рассмотренному примеру Book-Chapter, встречается на практике достаточно часто. Имеет смысл предложить некие типовые рекомендации касательно публичных операций, необходимых родительским классам для организации эффективной работы с набором дочерних объектов, с сохранением достаточной гибкости. Такие операции можно формировать в разных ситуациях по аналогии, изменяя лишь фрагменты названий методов и типы аргументов.
Итак, в предыдущем блоке в качестве стартовой точки было предложено создать 3 метода для формирования и просмотра набора дочерних объектов, скрыв при этом работу со структурой данных:
- метод, возвращающий текущее количество дочерних объектов:
int get XXX Count() const;
- метод, возвращающий дочерний объект либо ссылку на него по порядковому номеру:
- метод, добавляющий дочерний объект к родительскому:
void add XXX (XXX obj);
Разумеется, вместо XXX нужно подставить название или тип хранимых данных (например, Chapter).
В других задачах может понадобиться ряд дополнительных операций, в зависимости от потребностей. В частности, если требуется вставка нового элемента в конкретную позицию, а не в конец вектора, то понадобится метод, принимающий объект и желаемую позицию:
void insert XXX At (XXX obj, int index);
Также, достаточно часто требуется простейшая функциональность поиска. Встречаются две типичные формы - найти порядковый номер зарегистрированного в наборе дочернего объекта для последующего использования в методе getXXX, а также форма, где требуется лишь определить факт наличия или отсутствия объекта в дочернем наборе:
int find XXX Index (XXX obj) const; bool hasXXX (XXX obj) const;
Если реализация основана на векторе, подобные операции поиска нужно закладывать лишь для случаев с небольшим ожидаемым количеством элементов (до 10), т.к. такой примитивный алгоритм поиска на основе перебора и сравнения будет обладать линейной вычислительной сложностью.
В некоторых задачах может понадобиться функциональность удаления элементов. Удаление элементов может принимать несколько форм:
● удаление элемента, порядковый номер которого известен:
void remove XXX At (int index);
● удаление элемента, порядковый номер которого неизвестен (с поиском):
void remove XXX (XXX obj);
● удаление всех элементов:
void clearXXX ();
Стоит отметить, что функциональность удаления точно не нужно добавлять в родительский класс без реальной необходимости. Неудаляемые наборы дочерних объектов встречаются чуть ли не чаще, чем удаляемые, соответственно нет смысла выполнять лишнюю работу. Также, при удалении дочерних объектов нужно помнить отвечает ли родительский класс за их уничтожение. Иногда требуются 2 версии методов удаления - с уничтожением элемента и без уничтожения, т.е. разрыв связи, когда ответственность за уничтожение передается другому родителю.
Также, необходимо уяснить рекомендованные правила по способу передачи и возврата данных в операциях добавления, поиска и других. Ниже приведена таблица рекомендаций по способу передачи и возврата дочернего объекта в различных ситуациях в зависимости от характера дочерних объектов:
При возврате объектов-сущностей также допускается использование указателей вместо ссылок, если смысл метода состоит в поиске дочернего объекта по некоторому критерию, и результат может быть неудачным. Если искомый объект не найден, такой метод возвращает nullptr, в противном случае - адрес найденного объекта, удовлетворяющего искомым требованиям.
Ниже представлена более полная версия примера о книгах и главах, учитывающая приведенные рекомендации касательно стиля проектирования открытых операций родительского класса.
book.hpp
#ifndef _BOOK_HPP_ #define _BOOK_HPP_
/*****************************************************************************/
#include <string> #include <vector> #include <initializer_list>
/*****************************************************************************/
class Chapter;
/*****************************************************************************/
class Book {
/*-----------------------------------------------------------------*/
public:
/*-----------------------------------------------------------------*/
// Конструктор Book (std::string const & _title);
// Конструктор со списком глав Book (std::string const & _title, std::initializer_list< Chapter * > _chapters)
// Удаленные конструктор копий и оператор присвоения Book (const Book &) = delete; Book & operator = (const Book &) = delete;
// Деструктор ~Book ();
// Метод доступа к названию главы std::string const & getTitle () const;
// Метод, возвращающий количество глав int getChaptersCount () const;
// Метод, возвращающий главу по порядковому номеру Chapter & getChapter (int _index) const;
// Метод, возвращающий порядковый номер указанной главы int findChapterIndex (Chapter const & _chapter) const;
// Метод, подтверждающий наличие главы в книге bool hasChapter (Chapter const & _chapter) const;
// Метод, добавляющий главу в конец книги void addChapter (Chapter * _pChapter);
// Метод, добавляющий главу в книгу в конкретной позиции void insertChapter (int _atIndex, Chapter * _pChapter);
// Метод, удаляющий главу из книги в конкретной позиции void removeChapter (int _atIndex);
// Метод, удаляющий указанную главу из книги void removeChapter (Chapter const & _chapter);
// Метод удаления всех глав void clearChapters ();
/*-----------------------------------------------------------------*/
private:
/*-----------------------------------------------------------------*/
// Набор глав std::vector< Chapter * > m_chapters;
// Название книги const std::string m_title;
/*-----------------------------------------------------------------*/
};
/*****************************************************************************/
inline std::string const & Book::getTitle () const { return m_title; }
/*****************************************************************************/
// Реализация метода доступа к количеству глав Inline int Book::getChaptersCount () const { return m_chapters.size(); }
/*****************************************************************************/
// Реализация метода доступа к главе по порядковому номеру inline Chapter & Book::getChapter (int _index) const { return * m_chapters.at(_index); }
/*****************************************************************************/
#endif // _BOOK_HPP_
book.cpp
#include "book.hpp" #include "chapter.hpp"
/*****************************************************************************/
// Реализация конструктора Book::Book (std::string const & _title) : m_title(_title) {}
/*****************************************************************************/
// Реализация конструктора со списком глав Book::Book ( std::string const & _title, std::initializer_list< Chapter * > _chapters ) : m_title(_title), m_chapters(_chapters) {}
/*****************************************************************************/
// Реализация деструктора Book::~Book () { // Очистка уничтожит каждую главу clearChapters(); }
/*****************************************************************************/
// Реализация метода поиска порядкового номера главы int Book::findChapterIndex (Chapter const & _chapter) const { int nChapters = getChaptersCount(); for (int i = 0; i < nChapters; i++) if (m_chapters[ i ] == & _chapter) return i; // глава найдена
return -1; // глава не найдена }
/*****************************************************************************/
// Реализация метода, подтверждающего наличие главы в книге bool Book::hasChapter (Chapter const & _chapter) const { // Если глава есть в книге, порядковый номер будет найден успешно return findChapterIndex(_chapter)!= -1; }
/*****************************************************************************/
// Реализация метода добавления главы в конец книги void Book::addChapter (Chapter * _pChapter) { m_chapters.push_back(_pChapter); }
/*****************************************************************************/
// Реализация метода добавления главы в указанной позиции void Book::insertChapter (int _atIndex, Chapter * _pChapter) { m_chapters.insert(m_chapters.begin() + _atIndex, _pChapter); }
/*****************************************************************************/
// Реализация метода удаления главы по порядковому номеру void Book::removeChapter (int _atIndex) { delete m_chapters.at(_atIndex); m_chapters.erase(m_chapters.begin() + _atIndex); }
/*****************************************************************************/
// Реализация метода удаления указанной главы void Book::removeChapter (Chapter const & _chapter) { int index = findChapterIndex(_chapter); if (index == -1) throw std::logic_error("Chapter does not exists in book");
removeChapter(index); }
/*****************************************************************************/
// Реализация метода очистки всех глав книги void Book::clearChapters () { // Уничтожаем каждую главу for (Chapter * pChapter: m_chapters) delete pChapter;
// Очищаем контейнер m_chapters.clear(); }
/*****************************************************************************/
|
||||||||||||||||
Последнее изменение этой страницы: 2017-02-17; просмотров: 97; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.223.159.143 (0.006 с.) |