150
конкретному типу (например, создание и уничтожение образов). Обе функции после завершения
оставляют
ConstPtr
заблокированным.
Создание и уничтожение объектов
Пора заполнить кое-какие пробелы. Раз уж наши транзакции достаточно сложны, чтобы для них была
оправдана вся эта возня, они наверняка будут создавать или уничтожать объекты. Операции создания и
уничтожения также должны быть отменяемыми. Если объект создавался, операция отмены должна его
уничтожать, а если уничтожался — возвращать его из мертвых. Для этого придется внести изменения
как в класс
ConstPtr
,
так и в класс
LockPtr
. Мы уже сделали первый шаг в этом направлении,
объявив деструктор
ConstPtr
закрытым, чтобы им могли воспользоваться только
ConstPtr
или его
друзья. Давайте разберемся с оставшимися проблемами.
Изменения в классе ConstPtr
Несомненно, создание указываемого объекта представляет собой изменение и потому должно
осуществляться через
LockPtr
. Но
для того чтобы получить
LockPtr
, мы должны сначала иметь
ConstPtr
и его функцию
Lock()
. Следовательно, только
что описанный конструктор
ConstPtr
работать не будет — он создает уникальный объект перед вызовом
Lock()
.
ConstPtr
должен
находиться в состоянии
NULL
до тех пор, пока
LockPtr
не выделит память под объект и не закрепит
эти изменения. В
ConstPtr
необходимо внести следующие изменения:
•
В конструкторе без аргументов присваивать переменной
old_image
значение
NULL
.
•
Добавить оператор
!
, который проверяет, равен ли адрес значению
NULL
.
•
Инициировать исключение в операторе
->
, если адрес равен значению
NULL
.
•
Либо запретить копирование, либо присвоить копии
old_image
значение
NULL
.
Проблема с обычным конструктором копий
ConstPtr
заключается в том, что он может создать новую
копию указываемого объекта, но не позволит отменить ее создание. Ниже приводится новая версия
конструктора
ConstPtr
.
Определения функций, не изменившиеся по сравнению с показанной выше
упрощенной версией не показаны.
private:
ConstPtr(const ConstPtr&) : old_image(NULL), lock(NULL) {}
public:
ConstPtr() : old_image(NULL), lock(NULL) {}
bool operator!() { return old_image == NULL; }
const Type* operator->() const
{
if (old_image == NULL)
//
Исключение
return
old_image;
}
Изменения в классе LockPtr
Отныне
LockPtr
предстоит выполнять намного больше работы:
•
Он должен при необходимости создавать указываемый объект по требованию. Для этого в него
будет добавлена функция
Make()
.
•
Оператор
->
должен инициировать исключение, если адрес равен
NULL
.
Ниже приведены определения только изменившихся функций.
// В объявлении LockPtr
public:
void
Make();
//
Создать новый указываемый объект
void
Destroy();
//
Уничтожить указываемый объект