Министерство образования Республики Беларусь
Министерство образования Республики Беларусь
БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ
Кафедра эконмической информатики
Объектно-ориентированное программирование
“ ИСПОЛЬЗОВАНИЕ SMART-УКАЗАТЕЛЕЙ, МЕХАНИЗМА ТРАНЗАКЦИЙ И ИЕРАРХИИ КЛАССОВ”
Выполнила: Студентка группы
972303
Рушева Маргарита
Владиславовна
Проверила: Григорьева Юлия
Юрьевна
Минск, 2021
Применить знания, полученные в предыдущих работах, к реализации практических задач (реализация smart-указателей, механизма транзакций, иерархии классов).
ДИНАМИЧЕСКАЯ ПАМЯТЬ. ИНТЕЛЛЕКТУАЛЬНЫЕ УКАЗАТЕЛИ
Для управления динамической памятью в языке C++ используются два оператора: оператор new, который резервирует (а при необходимости и инициализирует) объект в динамической памяти и возвращает указатель на него; оператор delete, который получает указатель на динамический объект и удаляет его, освобождая зарезервированную память.
Интеллектуальный указатель (smart pointer) действует, как обычный указатель, но с важным дополнением: автоматически удаляет объект, на который он указывает.
Утечкой памяти (memory leak) называется ситуация, когда в программе нет ни одного указателя, хранящего адрес объекта, созданного в динамической памяти. Висячей ссылкой или висячим указателем (dangling pointer, wild pointer, dangling reference) называется указатель, ссылающийся на уже удалённый объект (или не ссылающийся на допустимый объект соответствующего типа).
Интеллектуальные указатели чрезвычайно важны для идиомы программирования RAII или Resource Acquisition Is Initialialization — получение ресурса является инициализацией. То есть, при получении какого-либо ресурса, его инициализируют в конструкторе, а, поработав с ним, корректно освобождают в деструкторе. Ресурсом может быть что угодно, к примеру файл, сетевое соединение или блок памяти.
ИСПОЛЬЗОВАНИЕ ТРАНЗАКЦИЙ
Транзакция в информатике − группа последовательных операций, которая представляет собой логическую единицу работы с данными. Транзакция может быть выполнена либо целиком и успешно, соблюдая целостность данных и независимо от параллельно идущих других транзакций, либо не выполнена вообще и тогда она не должна произвести никакого эффекта. При этом должно соблюдаться следующее: − если клиент начал и не завершил транзакцию, то другие клиенты не видят его изменений; − две транзакции не могут одновременно менять одни и те же данные. Для поддержки механизма транзакции объект должен содержать два указателя (на текущий объект и на объект, представляющий его предыдущее состояние) и функции (начать, закрепить, отменить действие).
Разработать набор классов (минимум 5 классов) по теме использование текстового редактора пользователями с автоматическим сохранением данных в файл. Редактор должен поддерживать возможность отмены внесенных изменений (отменить ввод, Undo, Ctrl+Z) и восстановления отмененной информации (вернуть ввод, Ctrl+Y, Redo). Для хранения историй модификации файла использовать список (его рациональную организацию определить самостоятельно). Разработанный набор классов должен иметь параметры типа. Все классы должны иметь методы получения и изменения своих полей. Использовать smart-указатели для создания программы, которая определяет возможность самостоятельного закрытия файла (т.е. данные файла сохранены и с ним никто сейчас не работает).
“input.h”
#pragma once
#pragma once
#include <iostream>
#include <conio.h>
#include <cstring>
void input(int& number)
{
int index = 0;
char str[4 + 1];
char ch;
bool sign = false;
do {
ch = _getch();
if (index == 0 && ch == '-' && !sign)
{
sign = true;
std::cout << "-";
}
else if (index == 0 && ch == 8 && sign)
{
std::cout << "\b \b";
sign = false;
}
if (ch == '\r' && index == 0)
{
ch = 0;
}
else if (index == 0 && ((ch >= '0' && ch <= '9')) && ch != 8)
{
std::cout << ch;
str[index] = ch;
index++;
}
else if (index > 0)
{
if (ch == 8)
{
index--;
str[index] = '\0';
std::cout << "\b \b";
}
else if (index >= 4)
{
;
}
else if (ch >= '0' && ch <= '9')
{
std::cout << ch;
str[index] = ch;
index++;
}
}
} while (ch != '\r');
str[index] = '\0';
std::cout << std::endl;
number = atoi(str);
if (sign) number *= -1;
}
void inputLat(std::string& str, int length)
{
int index = 0;
char ch;
do
{
ch = _getch();
if (ch == '\r' && index == 0)
{
ch = 0;
}
else if (ch == 8 && index > 0)
{
index--;
str.erase(index);
std::cout << "\b \b";
}
else if (index < 0 || index >= length)
{
;
}
else if ((ch >= '0' && ch <= '9') || ch == ' ' || ch == '№' || ch == '/' || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= 'а' && ch <= 'я') || (ch >= 'А' && ch <= 'Я') || (ch == 'ё' || ch == 'Ё'))
{
std::cout << ch;
str.push_back(ch);
index++;
}
} while (ch != '\r');
std::cout << std::endl;
}
“input.cpp”
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
#include <Windows.h>
#include "input.h"
using namespace std;
ostream& date(ostream& stream, int year, int day, int month)
{
if (day < 10) cout << "0";
cout << day << ".";
if (month < 10) cout << "0";
cout << month << ".";
cout << year;
return stream;
}
class Employee
{
public:
string name;
string place;
static const string file;
void output()
{
cout << name;
cout << " || " << place << endl;
}
void fwrite(ofstream& file)
{
for (int i = 0; i < name.size(); i++)
{
if (name.at(i) == ' ') name.at(i) = '.';
}
for (int i = 0; i < place.size(); i++)
{
if (place.at(i) == ' ') place.at(i) = '.';
}
file << name << endl;
file << place;
for (int i = 0; i < name.size(); i++)
{
if (name.at(i) == '.') name.at(i) = ' ';
}
for (int i = 0; i < place.size(); i++)
{
if (place.at(i) == '.') place.at(i) = ' ';
}
}
void fread(ifstream& file)
{
file >> name;
file >> place;
for (int i = 0; i < name.size(); i++)
{
if (name.at(i) == '.') name.at(i) = ' ';
}
for (int i = 0; i < place.size(); i++)
{
if (place.at(i) == '.') place.at(i) = ' ';
}
}
};
class Document
{
public:
static const string file;
string name;
string edInstitution;
int year;
int month;
int day;
void fwrite(ofstream& file)
{
for (int i = 0; i < name.size(); i++)
{
if (name.at(i) == ' ') name.at(i) = '.';
}
for (int i = 0; i < edInstitution.size(); i++)
{
if (edInstitution.at(i) == ' ') edInstitution.at(i) = '.';
}
file << name << endl;
file << edInstitution << endl;
file << year << endl;
file << month << endl;
file << day;
for (int i = 0; i < name.size(); i++)
{
if (name.at(i) == '.') name.at(i) = ' ';
}
for (int i = 0; i < edInstitution.size(); i++)
{
if (edInstitution.at(i) == '.') edInstitution.at(i) = ' ';
}
}
void fread(ifstream& file)
{
file >> name;
file >> edInstitution;
file >> year;
file >> month;
file >> day;
for (int i = 0; i < name.size(); i++)
{
if (name.at(i) == '.') name.at(i) = ' ';
}
for (int i = 0; i < edInstitution.size(); i++)
{
if (edInstitution.at(i) == '.') edInstitution.at(i) = ' ';
}
}
void output()
{
cout << "|| " << setiosflags(ios::left) << setw(25) << name;
cout << " | " << setw(20) << edInstitution;
cout << " | ";
date(cout, year, day, month) << endl;
}
void input()
{
cout << "Название документа : ";
inputLat(name, 25);
cout << "ВУЗ : ";
inputLat(edInstitution, 20);
cout << "Срок сдачи задания студентами" << endl;
cout << "День : ";
::input(day);
cout << "Месяц : ";
::input(month);
cout << "Год : ";
::input(year);
}
void inputTransaction(string edInstitution)
{
this->edInstitution = edInstitution;
cout << "Название документа : ";
inputLat(name, 25);
cout << "Срок сдачи задания студентами" << endl;
cout << "День : ";
::input(day);
cout << "Месяц : ";
::input(month);
cout << "Год : ";
::input(year);
}
void set(Document doc)
{
this->day = doc.day;
this->month = doc.month;
this->year = doc.year;
this->name = doc.name;
this->edInstitution = doc.edInstitution;
}
};
template <class T>
class Transaction
{
public:
T* prevState;
T* currentState;
Transaction(T* doc) {
prevState = NULL;
currentState = new T;
currentState = doc;
}
~Transaction() { delete currentState; delete prevState; }
void show()
{
cout << "состояния объекта" << endl;
if (prevState)
{
cout << "prevState = " << endl;
prevState->output();
cout << endl;
cout << "currentState = " << endl;
currentState->output();
cout << endl;
}
else
{
cout << "prevState = NULL" << endl;
cout << "currentState = " << endl;
currentState->output();
cout << endl;
}
}
bool BeginTransactions(T* newState)
{
delete prevState;
prevState = currentState;
currentState = new T(*prevState);
if (!currentState) return 0;
currentState->set(*newState);
return 1;
}
void commit()
{
prevState = NULL;
}
void DeleteTransactions()
{
if (prevState != NULL) {
currentState = NULL;
delete currentState;
currentState = prevState;
prevState = NULL;
}
}
T* operator->() { return currentState; };
};
template <class T>
struct Status {
T* ptr;
int counter;
};
template <typename T>
class SmartPointer {
Status<T>* smartPtr;
public:
static const string file;
SmartPointer(T* ptr = 0);
int showCounter() { return smartPtr->counter; }
~SmartPointer() {
if (smartPtr) {
smartPtr->counter--;
if (smartPtr->counter <= 0) {
delete smartPtr->ptr;
delete smartPtr;
}
}
}
T* operator->() const
{
if (smartPtr) return smartPtr->ptr;
else return NULL;
}
T& getPtr() const { return *smartPtr->ptr; }
SmartPointer(const SmartPointer& obj) :smartPtr(obj.smartPtr) {
if (smartPtr) smartPtr->counter++;
}
};
template <class T>
SmartPointer<T>::SmartPointer(T* ptr) {
smartPtr = new Status<T>;
smartPtr->ptr = ptr;
smartPtr->counter = 1;
}
template <class T>
class File
{
public: