126
Частные копии коллекций
Если итератор и его курсор не позволяют вносить изменения в коллекцию, существует простой выход:
создать частную копию коллекции в конструкторе итератора. На псевдокоде это выглядит так:
class Iterator {
private:
Collection
collection;
Cursor
location;
//
Текущая позиция в копии
public:
Iterator(Collection&
c)
: collection(c), location(collection.First()) {}
bool
More();
Foo*
Next();
};
Конструктор итератора с помощью конструктора копий класса
Collection
создает
вторую частную
копию коллекции. Перед вами — один из редких случаев, когда действительно имеет значение тот
факт, что переменные класса конструируются в порядке их перечисления; объект
collection
должен
быть сконструирован раньше объекта location, в противном случае вам предстоят мучения с отладкой
функции
First()
.
Коллекции объектов или коллекции указателей?
Эта схема обычно используется в ситуациях, когда коллекция состоит из указателей или ссылок на
объекты, которые во всем остальном никак не связаны с коллекцией. В
других коллекциях вместо
указателей или ссылок содержатся собственно объекты.
template
class Array {
private:
int
Size;
//
Количество объектов Type
Type
elements[size];
//
Объекты (внутренние)
// и т.д.
};
Здесь объекты буквально внедряются в коллекцию. Чтобы продублировать коллекцию, вам придется
скопировать не только указатели, но и объекты — а это может обойтись слишком дорого. С другой
стороны, может возникнуть необходимость в том, чтобы итератор возвращал указатель или ссылку на
исходный объект исходной коллекции, а не на копию. В любом случае вариант с частными
коллекциями отпадает.
Тот же принцип действует каждый раз, когда коллекция представляет собой набор ведущих указателей
на ее содержимое. Да, она содержит указатели, а не объекты, однако коллекция имеет право удалять
эти объекты, поэтому частная копия будет неустойчивой. Некоторые вопросы управления памятью,
связанные с этой проблемой — конкретнее, сборка мусора — рассматриваются в части 4 этой книги.
Упрощение частной коллекции
Предположим, исходная коллекция представляет собой бинарное дерево или другую сложную
структуру данных. Так ли необходимо воспроизводить в копии все дополнительные издержки
древовидной структуры, если учесть, что вы не собираетесь пользоваться индексированным доступом?
Существует общепринятое решение — создать в качестве частной копии упрощенный вариант
коллекции. Это будет проще, если в классе коллекции имеется оператор преобразования,
порождающий экземпляр упрощенной коллекции. Вместо конструктора копий коллекции итератор
использует ее оператор преобразования:
class SimpleCollection; //
Упрощенный вариант
class ComplexCollection {