// Направить указатель в стек

 void push (Type* _t) { array[iTop++]=_t; }

 // Вынуть указатель из стека

 Type* pop (void) {

  if (iTop == 0) return NULL;

  else return array[--iTop];

 }

 // Стек пуст?

 int isEmpty (void) { return iTop==0; }

 // Очистить стек

 void emptyAll (void) {

  for (int iCounter = 0; iCounter ‹ iTop; iCounter ++)

   if (*(array+iCounter)!= NULL) delete *(array+iCounter);

  iTop = 0;

 }

};

// Шаблон класса с многоуровневой отменой

template ‹class Type›

class MLTrans {

 typedef ampstack‹Type› stack;

private:

 Type* that; // Текущее значение

 stack history; // контейнер предыдущих значений

public:

 // конструктор-деструктор

 MLTrans(): that(new Type) {}

 ~MLTrans () { delete that; }

 // Сохранение текущего значения, aналог SAVE TRANSACTION в SQL серверах

 void Push() {

  history.push(that);

  that = new Type(*that);

 }

 // удаление промежуточных состояний

 void Commit () { history.emptyAll(); }

 // Откат на одну позицию; уничтожает текущее значение.

 void PopOne() {

  if (!history.isEmpty()) {

   delete that;

   that = history.pop();

  }

 }

 // Откат к началу транзакции.

 void Rollback() {

  Type* old = history.pop();

  Type* older = NULL;

  if (old!= NULL) {

   while ((older = history.pop())!= NULL) {

    delete old;

    old = older;

   }

   delete that;

   that = old;

  }

 }

 // Переопределенный operator-›

 Type* operator-›() { return that; }

}

// проверим работу

int main() {

 int t;

 MLTrans‹CType› a;

 a-›set(5);

 t = a-›get();

 a.Push();

 a-›set(6);

 t = a-›get();

 a.Push();

 t = a-›get();

 a-›set(7);

 t = a-›get();

 a.Push();

 t = a-›get();

 a-›set(9);

 t = a-›get();

// a.Push();

 t = a-›get();

 a.PopOne();

 t = a-›get();

 a.Rollback();

 t = a-›get();

 return 0;

}

Шаг 24 - Как создавать ТОЛЬКО локальные переменные.

В Шаге 17 мы изыскали способ подавить создание локальных переменных. Решим обратную задачу - как подавить иные способы их создания. А какие иные? Любые другие способы предполагают вызов оператора operator new() для выделения памяти и потом вызов конструктора. Значит, надо объявить operator new() закрытым членом класса, да и все. Ничего в нем делать не надо, а сразу назад. Попробуем?

class CNoHeap {

public:

 int a;

private:

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×