Чтение онлайн

на главную - закладки

Жанры

Идиомы и стили С++

Makhmutov Albert

Шрифт:

Неявные преобразования через конструкторы и операторы преобразований хороши, конечно. Но почему-то пришлось вводить ограничения на них. Чтоб неявно не вызывались. Сколь мне известно, компания Borland/Inprise собирась вводить в Delphi 4/5 перегрузку операторов, но как-то передумала…

Неявные объекты в большинстве случаев не мешают нам жить. Более того, запись в предыдущем шаге, где вызывается 7 конструкторов вместо 4, более читабельна-сопровождабельна, красива, соответствует духу и букве C++ (семантике и синтаксису). Если функция исполняется в программе раз в час, неважно, сколько раз вызовется в ней конструктор - 4 или 44. Скринсавер вообще выполняет

море абсолютно бесполезных и сверхсложных вычислений - Вам это мешает?

А что касается виртуальных функций, то и MFC, и OWL, и VCL– все используют их как можно реже - на то веские причины! Если бы все функции в них были виртуальными, то с полметра памяти уходило бы в каждой программе только на поддержание виртуальных таблиц, да по лишнему указателю в каждом объекте.

Есть такое правило "80-20": 20 процентов кода вызывает 80 процентов затруднений, 20 процентов кода занимает 80 процентов процессорного времени. Возможно, оно даже сильнее - "90-10". В данном Шаге это значит - не зашивайтесь в "дешевой" части кода.

В общем, я хочу сказать - перед тем, как применять какую-то технику, оцените - какие усилия Вы затратите на ее освоение, ее поддержание, и какой результат Вы получите (ожидаете получить), и пригодятся ли Вам эти знания в будущем, что тоже важно. Программирование - всегда поиск компромисса между затратами времени, пространства и (!)труда, не забывайте что Ваш день стоит минимум как небольшой DIMM. Надеюсь.

Шаг 22 - Классы объектов, поддерживающие транзакции.

Бывает особенно приятно, когда занимаешься теорией. Занимаешься, думаешь: "ну никакой связи с жизнью, хоть бы минимум пользы"… и вдруг раз! и польза является во всей своей красе, блистая в лучах солнца и хрустя пачками денег. Что чувствовал Менделеев, когда после долгих изысканий, жутких таблиц, являвшихся ему в ночных кошмарах, вдруг получил-таки нормальную, не паленую, 40-градусную водку? Или Эйлер, когда, после терзаний и депрессий, извлек таки сопротивляющийся, визжащий и цепляющийся щупальцами и жвалами квадратный корень из минус единицы? К чему это я? А вот к чему: концепция smart– указателей может предложить простые и прозрачные решения для некоторых сложных задач; и если Вы считаете, что поддержка транзакций (а так же многоуровневой отмены и повтора) есть сложная задача, то смарты помогут Вам с замечательной легкостью.

Вспомним для начала, что делает транзакция:

1. Если транзакция началась, то все изменения в ней либо вносятся вместе, либо не вносятся вообще (это вообще определение транзакции).

2. Если клиент начал и не завершил транзакцию, то другие клиенты не видят его изменений.

3. Две транзакции не могут одновременно изменять одни и те же данные.

Начнем с первого пункта. Если мы хотим закрепить или отменить проведенные изменения, нужно хранить состояние объекта на заданный момент - начало транзакции, и в момент принятия решения или уничтожать предыдущее состояние (закрепление) или возвращаться к нему (отмена). Пусть обслуживанием занимается smart– указатель. Кладем в него два указателя - один на текущий объект, а второй - на объект, представляющий его предыдущее состояние, и три функции - старт, закрепление, отмена.

#include ‹iostream.h›

// Некий скромный класс.

class CSomeClass {

public:

 int x;

 int y;

};

// Его оплетка: smart-pointer
с поддержкой отмены.

class CSimpleTr {

public:

 CSomeClass* that; // текущее значение

 CSomeClass* previos; // предыдущее значение

public:

 // конструктор-деструктор-присваивание-копирование

 CSimpleTr: previos(NULL), that(new CSomeClass) {}

 CSimpleTr(const CSimpleTr& _st): that(new CSomeClass(*(_st.that))), previos(NULL) {}

 ~CSimpleTr {delete that; delete previos;}

 CSimpleTr& operator=(const CSimpleTr& _st) {

if (this!=&_st) {

delete that;

that = new CSomeClass(*(_st.that));

}

return *this;

 }

 // начало транзакции

 void BeginTrans {

delete previos;

previos = that;

that = new CSomeClass(*previos);

 }

 // закрепление

 void Commit {

delete previos;

previos = NULL;

 }

 // отмена транзакции

 void Rollback {

if (previos != NULL) {

delete that;

that = previos;

previos = NULL;

}

 }

 // реализация указателя

 CSomeClass* operator-› { return that; }

};

int main (void) {

 // проверим быстренько

 CSimpleTr lvPair;

 lvPair-›x = 5;

 lvPair-›y = 8;

 lvPair.BeginTrans;

 lvPair-›x = 7;

 lvPair-›y = 11;

 lvPair.Rollback;

 lvPair.BeginTrans;

 lvPair-›x = 7;

 lvPair-›y = 11;

 lvPair.Commit;

 return 0;

}

Что может быть проще? Семантика значений, очевидно. Классы должны иметь полный набор обязательных функций, как обычно; в нашем случае класс CSomeClass больно уж тривиален, поэтому сойдет и так. Класс CSimpleTr имеет смысл переписать в виде шаблона, если не хотите его заново переписывать для каждого нового клиента, да еще добавить функцию isStarted. Функциональность на Ваш вкус и фантазию. MTS, например, восстановит отмененную транзакцию, если Вы после отмены сделаете закрепление: SetAbort; SetComplete; сработает так, как будто SetAbort; не было вовсе.

Поделиться:
Популярные книги

Адвокат империи

Карелин Сергей Витальевич
1. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.75
рейтинг книги
Адвокат империи

Вернуть Боярство

Мамаев Максим
1. Пепел
Фантастика:
фэнтези
попаданцы
5.40
рейтинг книги
Вернуть Боярство

Сколько стоит любовь

Завгородняя Анна Александровна
Любовные романы:
любовно-фантастические романы
6.22
рейтинг книги
Сколько стоит любовь

Жития Святых (все месяцы)

Ростовский Святитель Дмитрий
Религия и эзотерика:
религия
православие
христианство
5.00
рейтинг книги
Жития Святых (все месяцы)

Курсант: Назад в СССР 4

Дамиров Рафаэль
4. Курсант
Фантастика:
попаданцы
альтернативная история
7.76
рейтинг книги
Курсант: Назад в СССР 4

Иоанн Антонович

Сахаров Андрей Николаевич
10. Романовы. Династия в романах
Проза:
историческая проза
5.00
рейтинг книги
Иоанн Антонович

Вампиры девичьих грез. Тетралогия. Город над бездной

Борисова Алина Александровна
Вампиры девичьих грез
Фантастика:
фэнтези
6.60
рейтинг книги
Вампиры девичьих грез. Тетралогия. Город над бездной

Крещение огнем

Сапковский Анджей
5. Ведьмак
Фантастика:
фэнтези
9.40
рейтинг книги
Крещение огнем

Курсант: назад в СССР 9

Дамиров Рафаэль
9. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: назад в СССР 9

Пространство

Абрахам Дэниел
Пространство
Фантастика:
космическая фантастика
5.00
рейтинг книги
Пространство

Паладин из прошлого тысячелетия

Еслер Андрей
1. Соприкосновение миров
Фантастика:
боевая фантастика
попаданцы
6.25
рейтинг книги
Паладин из прошлого тысячелетия

Идеальный мир для Лекаря 20

Сапфир Олег
20. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 20

Печать пожирателя 2

Соломенный Илья
2. Пожиратель
Фантастика:
городское фэнтези
попаданцы
аниме
сказочная фантастика
5.00
рейтинг книги
Печать пожирателя 2

Кодекс Крови. Книга ХI

Борзых М.
11. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХI