В качестве примера, нуждающегося в управлении копированием класса для учета, рассмотрим два класса, которые могли бы использоваться в приложении обработки почты. Эти классы, 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 folders; // папки, содержащие это сообщение

 // вспомогательные функции, используемые конструктором копий,

 // оператором присвоения и деструктором

 // добавить это сообщение в папки, на которые указывает параметр

 void add_to_Folders(const Message&);

 // удалить это сообщение из каждой папки в folders

Перейти на страницу:

Похожие книги