- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Операторы присвоения, использующие копию и обмен, автоматически устойчивы к исключениям и правильно отрабатывают присвоение себя себе.
Упражнения раздела 13.3Упражнение 13.29. Объясните, почему вызов функции swap() в вызове swap(HasPtr&, HasPtr&) не приводит к бесконечной рекурсии.
Упражнение 13.30. Напишите и проверьте функцию swap() для подобной значению версии класса HasPtr. Снабдите свою функцию swap() оператором вывода примечания о ее выполнении.
Упражнение 13.31. Снабдите свой класс оператором < и определите вектор объектов класса HasPtr. Вставьте в вектор несколько элементов, а затем отсортируйте его (sort()). Обратите внимание на то, когда вызывается функция swap().
Упражнение 13.32. Получит ли преимущества подобная указателю версия класса HasPtr от определения собственной функции swap()? Если да, то в чем это преимущество? Если нет, то почему?
13.4. Пример управления копированием
Несмотря на то что управление копированием обычно необходимо для классов, резервирующих ресурсы, управление ресурсами не единственная причина определения этих функций-членов. У некоторых классов может быть необходимость в учете или других действиях, выполняемых функциями управления копированием.
В качестве примера, нуждающегося в управлении копированием класса для учета, рассмотрим два класса, которые могли бы использоваться в приложении обработки почты. Эти классы, Message и Folder, представляют соответственно сообщение электронной (или другой) почты и каталог, в котором могло бы находиться это сообщение. Каждое сообщение может находиться в нескольких папках. Но может существовать только одна копия содержимого любого сообщения. Таким образом, если содержимое сообщения изменится, эти изменения отображаются при просмотре данного сообщения в любой из папок.
Для отслеживания того, какие сообщения в каких папках находятся, каждый объект класса Message будет хранить набор указателей на объекты класса Folder, в которых они присутствуют, а каждый объект класса Folder будет содержать набор указателей на его объекты класса Message. Эту конструкцию иллюстрирует рис. 13.1.
Рис. 13.1. Проект классов Message и Folder
Класс Message будет предоставлять функции save() и remove() для добавления и удаления сообщений из папки. Для создания нового объекта класса Message следует определить содержимое сообщения, но не папку. Чтобы поместить сообщение в определенную папку, следует вызвать функцию save().
После копирования сообщения копия и оригинал будут разными объектами класса Message, но оба сообщения должны присутствовать в том же самом наборе папок. Таким образом, копирование сообщения скопирует содержимое и набор указателей на папку. Он должен также добавить указатель на недавно созданный объект класса Message к каждому из этих объектов класса Folder.
После удаления сообщения объект класса Message больше не существует. Поэтому его удаление должно удалять указатели на этот объект класса Message из всех объектов класса Folder, которые содержали это сообщение.
Когда один объект класса Message присваивается другому, содержимое (contents) левого сообщения заменяется таковым правого. Следует также модифицировать набор папок, удалив левый объект класса Message из предыдущих объектов класса Folder и добавив в них правый.
Глядя на этот список операций, можно заметить, что и деструктор, и оператор присвоения копии должны удалять заданное сообщение из папок, которые указывают на него. Точно так же и конструктор копий, и оператор присвоения копии добавляют объект класса Message в заданный список объекта класса Folder. Для решения этих задач определим пару закрытых вспомогательных функций.
Оператор присвоения копии зачастую осуществляет ту же работу, которая необходима в конструкторе копий и деструкторе. В таких случаях эти действия обычно помещают в закрытые вспомогательные функции.
Класс Folder будет нуждаться в аналогичных функциях-членах управления копированием для добавления и удаления себя из хранящих их объектов класса Message.
Проектирование и реализацию класса Folder оставим читателю в качестве самостоятельного упражнения, но будем подразумевать, что у него есть функции-члены addMsg() и remMsg(), выполняющие все действия по добавлению и удалению заданного сообщения из набора сообщений указанной папки.
Класс MessageС учетом проекта выше можно написать класс Message следующим образом:
class Message {
friend class Folder;
public:
// папки неявно инициализируются пустым набором
explicit Message(const std::string &str = ""):
contents(str) { }
// функции управления копированием, контролирующие указатели на
// это сообщение
Message(const Message&); // конструктор копий
Message& operator=(const Message&); // присвоение копии
~Message(); // деструктор
// добавить/удалить это сообщение из набора сообщений папки
void save(Folder&);
void remove(Folder&);
private:
std::string contents; // фактический текст сообщения
std::set<Folder*> folders; // папки, содержащие это сообщение
// вспомогательные функции, используемые конструктором копий,
// оператором присвоения и деструктором
// добавить это сообщение в папки, на которые указывает параметр
void add_to_Folders(const Message&);
// удалить это сообщение из каждой папки в folders
void remove_from_Folders();
};
Класс определяет две переменные-члена: contents — для хранения текста сообщения и folders — для хранения указателей на объекты класса Folder, в которых присутствует данное сообщение. Получающий строку конструктор копирует ее в переменную contents и (неявно) инициализирует переменную folders пустым набором. Поскольку у этого конструктора есть аргумент по умолчанию, он также является стандартным конструктором класса Message (см. раздел 7.5.1).
Функции-члены save() и remove()Кроме функций управления копированием, у класса Message есть только две открытых функции-члена: save(), помещающая сообщение в данную папку, и remove(), извлекающая его:
void Message::save(Folder &f) {
folders.insert(&f); // добавить данную папку в список папок
f.addMsg(this); // добавить данное сообщение в набор сообщений
}
void Message::remove(Folder &f) {
folders.erase(&f); // удалить данную папку из списка папок
f.remMsg(this); // удалить данное сообщение из набора сообщений
}
Чтобы сохранить (или удалить) сообщение, требуется модифицировать член folders класса Message. При сохранении сообщения сохраняется указатель на данный объект класса Folder; при удалении сообщения этот указатель удаляется.
Эти функции должны также модифицировать заданный объект класса Folder. Модификация этого объекта является задачей, контролируемой классом Folder при помощи функций-членов addMsg() и remMsg(), которые добавляют или удаляют указатель на данный объект класса Message соответственно.
Управление копированием класса MessageПри копировании сообщения копия должна появляться в тех же папках, что и оригинальное сообщение. В результате необходимо перебрать набор указателей класса Folder, добавляя указатель на новое сообщение в каждую папку, на которую указывал оригинал сообщения. Для этого и конструктор копий, и оператор присвоения копии должны будут выполнять те же действия, поэтому определим функцию для этой общей работы:
// добавить это сообщение в папки, на которые указывает m
void Message::add_to_Folders(const Message &m) {
for (auto f : m.folders) // для каждой папки, содержащей m,
f->addMsg(this); // добавить указатель на это сообщение
// в данную папку
}
Здесь происходит вызов функции addMsg() для каждого объекта класса Folder в m.folders. Функция addMsg() добавит указатель на этот объект класса Message в данный объект класса Folder.

