
- •Учебное пособие
- •Введение
- •Объектно-ориентированный подход
- •Объектно-ориентированное программирование Абстрактные типы данных
- •Базовые принципы объектно-ориентированного программирования
- •Простейший ввод и вывод
- •Объект cout
- •Манипуляторы hex и oct
- •Другие манипуляторы
- •Объект cin
- •Операторы для динамического выделения и освобождения памяти (new и delete)
- •Базовые конструкции объектно-ориентированных программ Объекты
- •Понятие класса
- •Конструктор копирования
- •Конструктор explicit
- •Указатели на компоненты класса
- •Встроенные функции (спецификатор inline)
- •Организация внешнего доступа к локальным компонентам класса (спецификатор friend)
- •Вложенные классы
- •Static-члены (данные) класса
- •Указатель this
- •Компоненты-функции static и const
- •Proxi-классы
- •Параметры ссылки
- •Независимые ссылки
- •Практические приемы ограничения числа объектов класса
- •Наследование (производные классы)
- •Конструкторы и деструкторы при наследовании
- •Виртуальные функции
- •Абстрактные классы
- •Виртуальные деструкторы
- •Множественное наследование
- •Виртуальное наследование
- •Перегрузка функций
- •Перегрузка операторов
- •Перегрузка бинарного оператора
- •Перегрузка унарного оператора
- •Дружественная функция operator
- •Перегрузка оператора []
- •Перегрузка оператора ()
- •Перегрузка операторов new и delete
- •Преобразование типа
- •Явные преобразования типов
- •Преобразования типов, определенных в программе
- •Шаблоны Параметризированные классы
- •Передача в шаблон класса дополнительных параметров
- •Шаблоны функций
- •Совместное использование шаблонов и наследования
- •Шаблоны класса и friend
- •Некоторые примеры использования шаблона класса Реализация smart-указателя
- •Классы поддерживающие транзакции
- •Задание значений параметров класса по умолчанию
- •Пространства имен
- •Ключевое слово using как директива
- •Ключевое слово using как объявление
- •Псевдоним пространства имен
- •Организация ввода-вывода
- •Состояние потока
- •Строковые потоки
- •Организация работы с файлами
- •Организация файла последовательного доступа
- •Создание файла произвольного доступа
- •Основные функции классов ios, istream, ostream
- •Основы обработки исключительных ситуаций
- •Перенаправление исключительных ситуаций
- •Исключительная ситуация, генерируемая оператором new
- •Генерация исключений в конструкторах
- •Задание собственной функции завершения
- •Спецификации исключительных ситуаций
- •Задание собственного неожиданного обработчика
- •Иерархия исключений стандартной библиотеки
- •Стандартная библиотека шаблонов (stl) Общее понятие о контейнере
- •Общее понятие об итераторе
- •Категории итераторов
- •Основные итераторы
- •Вспомогательные итераторы
- •Операции с итераторами
- •Контейнерные классы Контейнеры последовательностей
- •Контейнер последовательностей vector
- •Контейнер последовательностей list
- •Контейнер последовательностей deque
- •Ассоциативные контейнеры
- •Ассоциативный контейнер multiset
- •Ассоциативный контейнер set
- •Ассоциативный контейнер multimap
- •Ассоциативный контейнер map
- •Адаптеры контейнеров
- •Адаптеры stack
- •Адаптеры queue
- •Адаптеры priority_queue
- •Пассивные и активные итераторы
- •Алгоритмы
- •Алгоритмы сортировки sort, partial_sort, sort_heap
- •Алгоритмы поиска find, find_if, find_end, binary_search
- •Алгоритмы fill, fill_n, generate и generate_n
- •Алгоритмы equal, mismatch и lexicographical_compare
- •Математические алгоритмы
- •Алгоритмы работы с множествами
- •Алгоритмы swap, iter_swap и swap_ranges
- •Алгоритмы copy, copy_backward, merge, unique и reverse
- •Примеры реализации контейнерных классов Связанные списки
- •Реализация односвязного списка
- •Реализация двусвязного списка
- •Реализация двоичного дерева
- •Литература
- •Вопросы по курсу ооп
- •220013, Минск, п.Бровки, 6.
Классы поддерживающие транзакции
Концепция smart-указателей позволяет просто решать задачу поддержки транзакций.
Если транзакция началась, то все изменения в ней либо вносятся вместе, либо не вносятся вообще;
если клиент начал и не завершил транзакцию, то другие клиенты не видят его изменений;
две транзакции не могут одновременно менять одни и те же данные.
Если требуется закрепить или отменить выполненные изменения, то необходимо хранить состояние объекта на заданный момент - начало транзакции, и в момент принятия решения или уничтожать предыдущее состояние (закрепление) или возвращаться к нему (отмена). Для этого может быть использован smart-указатель. Основой его являются два указателя - один на текущий объект, а второй - на объект, представляющий его предыдущее состояние, и три функции - старт, закрепление, отмена.
#include <iostream.h>
template <class T1>
class Cls
{ T1 x;
public:
Cls() : x(0){}
f(int X) {x=X;}
T1 Show()
{return xl;}
};
// smart-pointer с поддержкой отмены.
template <class T2>
class Tran
{ T2* that; // текущее значение объекта класса Cls
T2* prev; // предыдущее значение объекта класса Cls
public:
Tran():prev(NULL), that(new T2){}; // конструктор
Tran(const Tran & obj): // конструктор копирования
that(new T2(*(obj.that))), prev(NULL) {};
~Tran(){delete that; delete prev;}; // деструктор
Tran& operator=(const Tran & obj); // перегрузка присваивания
void Show(); // отображение значений (предыдущего и
// текущего) объекта класса Cls
void BeginTrans(); // начало транзакции
void Commit(); // закрепление
void DeleteTrans(); // отмена транзакции
T2* operator->(); // реализация указателя
};
template <class T2>
Tran<T2>& Tran<T2>::operator=(const Tran<T2> & obj)
{ if (this != &obj) // проверка на случай obj=obj
{ delete that; // удаление текущего значения объекта
that = new T2(*(obj.that)); // создание и копирование
}
return *this;
}
template <class T2>
T2* Tran<T2>::operator->() {return that;}
template <class T2>
void Tran<T2>::Show()
{ cout<<"состояния объекта"<<endl;
if (prev) cout<<"prev = "<<prev->get()<<endl;
cout<<"that = "<<that->get()<<endl;
}
template <class T2>
void Tran<T2>::BeginTrans()
{ delete prev; // удаление предыдущего значения
prev = that; // текущее становится предыдущим
that = new T2(*prev); // новое значение текущего значения
}
template <class T2>
void Tran<T2>::Commit ()
{ delete prev; // удаление предыдущего значения
prev = NULL; // предыдущего состояния нет
}
template <class T2>
void Tran<T2>::DeleteTrans()
{ if (prev != NULL)
{ delete that; // удаление текущего значения
that = prev; // предыдущее становится текущим
prev = NULL; // предыдущего состояния нет
}
}
int main (void)
{ Tran<Cls<int> > tr;
tr->f(5);
tr.Show();
tr.BeginTrans();
tr.Show();
tr->f(7);
tr.Show();
tr.DeleteTrans();
tr.Show();
tr.BeginTrans();
tr.Show();
tr->f(7);
tr.Commit();
tr.Show();
return 0;
}
Результат работы программы:
состояния объекта
that = 5
состояния объекта
prev = 5
that = 5
состояния объекта
prev = 5
that = 7
состояния объекта
that = 5
состояния объекта
prev = 5
that = 5
состояния объекта
that = 7
Следует отметить, что перегрузка операции присваивания (=) понадобится в случае, например, если описаны два объекта.
Tran<Cls<int> > tr,ts;
. . .
ts=tr; // требуется перегрузка операции =