Программирование >>  Синтаксис инициирования исключений 

1 ... 37 38 39 [ 40 ] 41 42 43 ... 82


bool At(void* key, void*& value); void RemoveEntry(void* key);

typedef void* Slot; Настоящее объявление надежно спрятано Slot First(); Возвращает Slot для перебора

Эквивалент нашей функции Peek

bool GetCurrent(Slot slot, void*& key, void*& value);

Эквивалент нашей функции Next

bool GetNext(Slot& slot, void*& key, void*& value);

Функция AddEntry() заносит в словарь новое значение с заданным ключом. Если ключ уже существует для другого значения, значение заменяется новым. Функция At() возвращает логический код, который показывает, присутствует ли ключ в словаре; если присутствует, функция возвращает true и value (значение, соответствующее данному ключу). Функция RemoveEntry() удаляет ключ и связанное с ним значение. Функция First() возвращает пассивный итератор, направленный таким образом, чтобы первый вызов GetNext() возвратил первый элемент словаря. Функция GetCurrent() возвращает пару ключ/значение, находящуюся в текущей позиции Slot. Функция GetNext() возвращает пару ключ/значение и перемещает итератор к следующему элементу. Единственное отличие между этими функциями заключается в перемещении логической позиции после получения объекта.

Мы воспользуемся словарем следующим образом: ключом будет объект, хранящийся в нашем наборе, а значением этого ключа - журнал вставок/удалений для данного объекта.

Класс журнала

Ниже приведен открытый интерфейс класса, в котором хранится история вставок/удалений для объекта. Этот класс использует рассмотренный выше класс Timestamp - он образует вторую составляющую пар ключ/значение, хранящихся в словаре. В реализации нет ничего интересного, поэтому я ее пропускаю.

class History { public:

History(); Пустой журнал

void Insert(Timestamp); Вставка в заданное время void Remove(Timestamp); Удаление в заданное время bool Exists(Timestamp); В заданное время bool Exists(); В настоящий момент

Функция Exists(Timestamp) возвращает true, если в заданное время последней операцией была вставка, и false - если последней операцией было удаление или до этого времени вообще не было операций. Безаргументная функция Exists() является синонимом для Exists(Timestamp) с очень большим значением времени - то есть до настоящего момента.

Абстрактный базовый класс

Класс набора делится на две части: абстрактный базовый класс, работающий с void*, и производный параметризованный класс, в который добавлена безопасность типов. Абстрактный базовый класс выглядит так:

В файле Set.h

class SetBase : private Dictionary { friend class InternalIterator; protected:

SetBase(); Чтобы класс был абстрактным



public:

class Iterator { Базовый класс внешнего итератора public:

virtual bool More() = 0;

virtual Type* Next() = 0;

Iterator* SetBase::ProvideIterator()

return new InternalIterator(this);

void SetBase::AddObject(void* entry)

void* v; History* h;

if (At(entry, v)) { Уже есть - проверить время h = (History*)v;

if (!h->Exists()) Необходимо выполнить вставку h->Insert(Timestamp());

else { Еще нет h = new History; h->Insert(Timestamp()); AddEntry(entry, h);

void SetBase::RemoveObject(void* entry)

void* v; History* h;

if (At(entry, v)) { Уже есть - проверить время h = (History*)v;

if (h->Exists()) Необходимо выполнить удаление h->Remove(Timestamp());

bool SetBase::Exists(void* entry, Timestamp ts) void* v;

return At(entry, v) && ((History*)v)->Exists(ts); bool SetBase::Exists(void* entry) void* v;

return At(entry, v) && ((History*)v)->Exists();

Существуют и другие возможности, которые можно было добавить, но и показанного вполне хватит для демонстрации рассматриваемой методики.



Внутренний итератор

Чтобы реализовать функцию ProvideIterator() , мы создаем как нетипизированный внутренний итератор, ограниченный файлом .cpp и производный от SetBase::Iterator , так и внешний - в виде параметризованной, безопасной по отношению к типам оболочки. Ниже приведен код внутреннего итератора, объявленного статически (то есть локального по отношению к файлу .cpp). Вся логика временных пометок спрятана в реализации этого класса.

В файле set.cpp

class InternalIterator : public SetBase::Iterator { private:

Dictionary* dictionary;

Dictionary::Slot* slot; Текущая позиция Timestamp my time; Время рождения данного итератора

public:

InternalIterator(Dictionary* d)

: dictionary(d), s1ot(d->First()), my time() {} virtual bool More(); virtual void* Next();

bool InternalIterator::More()

void* key; void* h;

if (!dictionary->GetCurrent(s1ot, key, h))

return false; позиция выходит за текущие границы

if (((History*)h)->Exists(my time)) return true; while (dictionary->GetNext(s1ot, key, h)); return false;

void* InternalIterator::Next()

void* key; void* keyl; void* h;

Предполагается, что клиент сначала вызвал More(), поэтому объект GetNext() не устарел dictionary->GetCurrent(s1ot, key, h); dictionary->GetNext(s1ot, keyl, h); return key;

Параметризованная оболочка, безопасная по отношению к типам

Наконец, в приведенном ниже параметризованном классе все становится безопасным по отношению к типам и начинает радовать глаз. Внешний итератор представляет собой параметризованную оболочку для внутреннего итератора, предоставляемого SetBase.

template <c1ass Type>

class Set : private SetBase {



1 ... 37 38 39 [ 40 ] 41 42 43 ... 82

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика