logo
шпоры по ООП

56.Создание шаблонного класса.

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

Давайте сначала рассмотрим вполне тривиальный пример, просто чтобы привыкнуть к используемому синтаксису. Рассматриваемый далее пример - класс, который хранит пару значений. Принадлежащие функции этого класса передают минимальное и максимальное значения, а также позволяют определить, являются ли два значения одинаковыми. Еще раз повторю, что раз перед нами шаблон класса, то тип значения может быть почти любым.

template <class T>

class Pair

{

T a, b;

public:

Pair (T t1, T t2);

T Max();

T Min ();

int isEqual ();

};

Пока все выглядит также изящно, как и для шаблонов функций. Единственная разница состоит в том, что вместо описания функции используется объявление класса. Шаблоны классов становятся все более сложными, когда вы описываете принадлежащие функции класса. Вот, например, описание принадлежащей функции Min() класса Pair:

template <class T>

T Pair <T>::Min()

{

return a < b ? a : b;

}

Чтобы понять эту запись, давайте вернемся немного назад. Если бы Pair был обычным классом (а не шаблоном класса) и T был бы некоторым конкретным типом, то функция Min класса Pair была бы описана таким образом:

T Pair::Min()

{

return a < b ? a : b;

}

Для случая шаблонной версии нам необходимо, во-первых, добавить заголовок шаблона template <class T>

Затем нужно дать имя классу. Помните, что на самом деле мы описываем множество классов - семейство Pair. Повторяя синтаксис префикса (заголовка) шаблона, экземпляр класса Pair для целых типов, можно назвать Pair<int>, экземпляр для типа double - Pair<double>, для типа Vector - Pair<Vector>. Однако в описании принадлежащей функции нам необходимо использовать имя класса Pair<T>. Это имеет смысл, так как заголовок шаблона говорит, что Т означает имя любого типа.

Приведем текст остальных методов класса Pair. Описания методов помещаются в заголовочный файл, так как они должна быть видимы везде, где используется класс Pair.

// конструктор

template <class T>

Pair <T>::Pair (T t1, T t2) : a(t1), b(t2)

{}

// метод Max template <class T>

T Pair <T>::Max()

{

return a>b ? a : b;

}

// метод isEqual template <class T>

int Pair <T>::isEqual()

{

if (a==b) return 1;

return 0;

}

Ранее уже отмечалось, что шаблоны функций могут работать только для тех (встроенных) типов данных или классов, которые поддерживают необходимые операции. То же самое справедливо и для шаблонов классов. Чтобы создать экземпляр класса Pair для некоторого классового типа, например для класса X, этот класс должен содержать следующие общедоступные функции

X (X &); // конструктор копирования

int operator == (X)

int operator < (X);

Три указанные функции необходимы, так как они реализуют операции, выполняемые над объектами типа T в метода шаблона класса Pair.

Если вы собираетесь использовать некоторый шаблон класса, как узнать какие операции требуются? Если шаблон класса снабжен документацией, то эти требования должны быть в ней указаны. В противном случае придется читать первичную документацию - исходный текст шаблона. При этом учитывайте, что встроенные типы данных поддерживают все стандартные операции.