Некоторые примеры использования шаблона класса

При использовании в программе указателя на объект, память для которого выделена с помощью оператора new, в случае если объект становится не нужен, то для его разрушения необходимо явно вызвать оператор delete. В то же время на один объект могут ссылаться множество указателей и, следовательно, нельзя однозначно сказать, нужен ли еще этот объект или он уже может быть уничтожен. Рассмотрим пример реализации класса, для которого происходит уничтожение объектов, в случае если уничтожается последняя ссылка на него. Это достигается тем, что наряду с указателем на объект хранится счетчик числа других указателей на этот же объект. Объект может быть уничтожен только в том случае, если счетчик ссылок станет равным нулю.

#include "iostream.h"

#include "string.h"

template <class T>

struct Status // состояние указателя

{ T *RealPtr; // указатель

int Count; // счетчик числа ссылок на указатель

};

template <class T>

class Point // класс-указатель

{ Status<T> *StatPtr;

public:

Point(T *ptr=0); // конструктор

Point(const Point &); // копирующий конструктор

~Point();

Point &operator=(const Point &); // перегрузка

// Point &operator=(T *ptr); // перегрузка

T *operator->() const;

T &operator*() const;

};

Приведенный ниже конструктор Point инициализирует объект указателем. Если указатель равен NULL, то указатель на структуру Status, содержащую указатель на объект и счетчик других указателей, устанавливается в NULL. В противном случае создается структура Status

template <class T>

Point<T>::Point(T *ptr) // описание конструктора

{ if(!ptr) StatPtr=NULL;

else

{ StatPtr=new Status<T>;

StatPtr->RealPtr=ptr;

StatPtr->Count=1;

}

}

Копирующий конструктор StatPtr не выполняет задачу копирования исходного объекта, а так как новый указатель ссылается на тот же объект, то мы лишь увеличиваем число ссылок на объект.

template <class T> // описание конструктора копирования

Point<T>::Point(const Point &p):StatPtr(p.StatPtr)

{

if(StatPtr) StatPtr->Count++; // увеличено число ссылок

}

Деструктор уменьшает число ссылок на объект на 1, и при достижении значения 0 объект уничтожается

template <class T>

Point<T>::~Point() // описание деструктора

{ if(StatPtr)

{ StatPtr->Count--; // уменьшается число ссылок на объект

if(StatPtr->Count<=0) // если число ссылок на объект <=0,

{ delete StatPtr->RealPtr; // то уничтожается объект

delete StatPtr;

}

}

}

template <class T>

T *Point<T>::operator->() const

{ if(StatPtr) return StatPtr->RealPtr;

else return NULL;

}

template <class T>

T &Point<T>::operator*() const // доступ к StatPtr осуществляется

{ if(StatPtr) return *StatPtr->RealPtr; // посредством this-указателя

else throw bad_pointer; // исключительная ситуация

}

При выполнении присваивания вначале необходимо указателю слева от знака = отсоединиться от ”своего” объекта и присоединиться к объекту, на который указывает указатель справа от знака =.

template <class 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;

};

void 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;

}

 

Порядок выполнения работы

 

1. Изучить краткие теоретические сведения.

2. Ознакомиться с материалами литературных источников [1,2,3,4,5].

3. Разработать алгоритм программы.

4. Написать, отладить и выполнить программу.

 

Варианты заданий

 

1. Напишите шаблон класса для работы с одномерным массивом. Реализуйте функции ввода\вывода массива на экран. Перегрузите оператор [] для получения элемента массива с проверкой размера массива. Определите несколько массивов разных типов и поработайте с их данными.

2. Напишите шаблон класса для работы с одномерным массивом. Реализуйте функции ввода\вывода массива на экран. Перегрузите операторы >, < для сравнения размеров массива. Определите несколько массивов разных типов и поработайте с их данными.

3. Напишите шаблон класса для работы с очередью. Реализуйте функции работы с данными очереди. Определите несколько очередей разных типов и поработайте с их данными.

4. Напишите шаблон класса для работы со стеком. Реализуйте функции работы с данными стека. Определите несколько очередей разных типов и поработайте с их данными.