Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lectures_2.doc
Скачиваний:
28
Добавлен:
15.03.2015
Размер:
511.49 Кб
Скачать

Шаблоны классов и отношение включения

Шаблон класса может использоваться в качестве компонента другого шаблона. В реализации шаблона Stackв качестве его компонента используется шаблон массива.

// Компонент (часть) template<typename T> class Array { // ... }; // Композит (общий) template <typename T> class Stack { public: // ... private: Array<T> ar; // ... };

Рекурсивное использование шаблонов классов

Шаблоны классов можно применять рекурсивно. Пусть имеется следующий шаблон массива.

template <typename T, int size> class Array { // ... };

Располагая таким определением шаблона, его можно использовать следующим образом:

Array<Array<int, 5>, 10>matrix;

Это определение создает массив, состоящий из 10 элементов, каждый из которых в свою очередь является массивом из 5 элементов типа int. Таким образом, получаем двумерный массив, который может хранить до 10 строк и 5 столбцов.

Если в шаблоне Arrayперегружен операторoperator[], то к элементамmatrixможно обращаться следующим образомmatrix[i][j].

Друзья и шаблоны классов

При использовании «друзей» в шаблонах классов возникают определенные трудности. Ограничимся рассмотрением этого вопроса применительно к «дружественным» функциям. Более того, будем рассматривать конкретный пример, в котором для шаблона Arrayнеобходимо перегрузить оператор поместить в поток «<<».

Рассмотрим два варианта такой перегрузки.

  1. Легко реализуемый вариант, когда определение перегружающей функции располагается в теле шаблона: недостаток – несоответствие стилю хорошего программирования.

  2. Более сложно реализуемый вариант, но отвечающий хорошему стилю программирования, когда определение перегружающей функции находится вне тела шаблона.

Вариант 1.

template <typename T> class Array { public: friend ostream7 operator<<(ostream& os, const Array<T>& rhs) { // ... } };

Вариант 2.

Здесь необходимы следующие дополнительные компоненты:

  • Опережающее объявление для перегружающей шаблонной функции.

  • Указание в теле шаблонного класса на то, что дружественная функция является шаблоном.

// Опережающее объявление для шаблонного класса Array, // необходимо для последующего опережающего объявления // дружественной функцииtemplate<typenameT>classArray; // Опережающее объявление дружественной функцииtemplate<typenameT>ostream&operator<< (ostream&os,constArray<T>&rhs);template<typenameT>classArray{public:friendostream&operator<< <>(ostream&os,constArray<T>rhs); // ... };template<typenameT>ostream&operator<<(ostream&os,constArray<T>&rhs) { // ... }

Явная и частичная специализация шаблона класса

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

Частичная специализация – это альтернативное определение шаблона класса, в котором некоторые из параметров шаблона заменены аргументами. Явная специализация имеет место, когда в частичной специализации выполнена замена всех параметров шаблона.

Здесь могут быть полезными следующие понятия:

  • Первичный шаблон.

  • Вторичный шаблон.

Первичный шаблон – это исходный шаблон, а вторичный шаблон – его специализация.

Пример.

// Первичный шаблон template<typenameT1,typenameT2>classPair{ // ... }; // Частичная специализация. // Зафиксирован второй параметр шаблонаtemplate<typenameT1>classPair<T1,int> { // ... }; // Явная специализация. // Зафиксированы все параметры шаблонаtemplate <> class Pair<int, int> {

// ... };

Обсуждение.

Основной принцип использования состоит в том, что компилятор выбирает наиболее специализированный шаблон.

Пусть имеется следующий клиентский программный код

Pair <double, double> pr1;

В этом случае ни один из вторичных шаблонов не подходит. Поэтому будет использоваться первичный шаблон.

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

Pair <double, int> pr2;

В этом случае будет использоваться частичная специализация.

Наконец для клиентского кода

  1. Pair <int, int> pr3;

будет использована явная специализация.

Соседние файлы в предмете Программирование