Реализация smart-указателя
Если при использовании в программе указателя на объект, память для которого выделена с помощью оператора new, объект становится не нужен, то для его разрушения необходимо явно вызвать оператор delete. В то же время на один объект могут ссылаться множество указателей и, следовательно, нельзя однозначно сказать, нужен ли еще этот объект или он уже может быть уничтожен.
template <typename T>
struct Status { T *RealPtr; int Count;
};
template <typename T>
class Point
{ Status <T> *StatPtr;
Public:
Point (T * ptr = 0);
Point(const Point & );
~Point();
Point & operator =(const Point &);
T * operator->() const;
T & operator*() const;
void get_count() {cout<<StatPtr->Count<<endl;}
};
template<typename T>
Point<T>::Point(T * ptr)
{ if(!ptr)
StatPtr = NULL;
else
{ StatPtr = new Status <T>; StatPtr->RealPtr=ptr; StatPtr->Count = 1;
}
}
template <typename T>
Point<T>::Point(const Point & p): StatPtr(p.StatPtr)
{ if(StatPtr) StatPtr->Count++;
}
template <typename T>
Point<T>::~Point()
{ if(StatPtr)
{ StatPtr->Count--;
if(StatPtr->Count <= 0)
{delete StatPtr->RealPtr; delete StatPtr;
}
}
}
template <typename T>
T * Point <T>::operator->() const
{ if(StatPtr)
return StatPtr->RealPtr;
else return NULL;
}
template <typename T>
T & Point<T>::operator *() const
{ if(StatPtr) return *StatPtr->RealPtr;
else throw "Opps";
}
template <typename T>
Point<T> & Point<T>::operator =(const Point & p)
{ if(StatPtr)
{StatPtr->Count--;
if(StatPtr->Count <= 0)
{delete StatPtr->RealPtr; delete StatPtr;
}
}
StatPtr = p.StatPtr;
if(StatPtr) StatPtr->Count++; return * this;
}
struct Str
{ int a;
char c;
};
int main()
{ Point<Str> pt1(new Str); // генерация класса Point, конструирование
// объекта pt1, инициализируемого указателем
// на структуру Str, далее с объектом можно
// обращаться как с указателем
Point<Str> pt2=pt1,pt3; // для pt2 вызывается конструктор копирования,
// затем создается указатель pt3
pt3=pt1; // pt3 переназначается на объект указателя pt1
(*pt1).a=12; // operator*() получает this указатель на pt1
(*pt1).c='b';
int X=pt1->a; // operator->() получает this-указатель на pt1
char C=pt1->c;
return 0:
}
47.Свойства в С++.
В общем случае, свойство − это пара функций (public), одна из которых отвечает за установку компонент-данных (private) объекта, а другая за их считывание. Такое решение позволяет обеспечить инкапсуляцию данных. Необходимость использования свойств возникает тогда, когда при изменении некоторого параметра требуется произвести ещё некоторые действия.
Наиболее простой способ обеспечения инкапсуляции в C++ заключается в написании пары функций типа get_val() и put_val() для каждого параметра.
Модификатор _declspec получил дополнительный параметр «property». Это позволяет
в классе объявить «виртуальную» переменную и связать её с соответствующими
функциями.
class cls
{ int m;
public:
_declspec(property(get=get_val, put=put_val)) int V;
int get_val()
{ return m; }
void put_val(int v)
{ m = v; }
};
Мэин:
cls obj;
obj.V = 50; // при этом выполняется вызов put_val()
int k = obj.V; // при этом выполняется вызов get_val()
Основной недостаток:
Зависимость от компилятора. Нарушается инкапсуляция
Транзакции.
Транзакция может быть выполнена либо целиком и успешно, соблюдая целостность данных и независимо от параллельно идущих других транзакций, либо не выполнена вообще и тогда она не должна произвести никакого эффекта.
Пример: Необходимо перевести с банковского счёта номер 5 на счёт номер 7 сумму в 10 денежных единиц. Этого можно достичь, к примеру, приведённой последовательностью действий:
- Начать транзакцию( прочесть баланс на счету номер 5; уменьшить баланс на 10 денежных единиц;сохранить новый баланс счёта номер 5;прочесть баланс на счету номер 7;увеличить баланс на 10 денежных единиц; сохранить новый баланс счёта номер 7
- Окончить транзакцию
Эти действия представляют из себя логическую единицу работы «перевод суммы между счетами», и таким образом, являются транзакцией. Если прервать данную транзакцию, к примеру, в середине, и не аннулировать все изменения, легко оставить владельца счёта номер 5 без 10 единиц, тогда как владелец счета номер 7 их не получит.
____________________
template <class T1>
class A
{
T1 x;
public:
void set(T1 X){x=X;}
T1 get(){return x;}
void Show(){cout<<x<<endl;}
};
template <class T2>
class Tran
{
T2 *that; //текущее значение объекта класса A
T2 *prev; //предыдущее…
public:
Tran(){prev = NULL; that = new T2;}
Tran(const Tran &obj):that(new T2(*(obj.that))),prev(NULL){}//constr copy for A
~Tran() {delete prev; delete that;}
Tran &operator = (const Tran & obj);
void Show();
void Begin_Tran(); //начать
void Commit(); //закрепить
void Del_Tran(); //отменить
T2 *operator->();
};
template <class T2>
Tran <T2> & Tran <T2>::operator = (const Tran & obj)
{
if(this!=&obj) { delete that; that = new T2(*(obj.that)); } //prev не трогаем, чтобы
return *this; // можно было сделать откат
}