Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шаблоны_Generic.doc
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
94 Кб
Скачать
☆

1.2. Шаблоны классов

Шаблоны классов определяются как тип данного с заранее неизвестными типами полей и других элементов класса, и также позволяют работать с данными разных типов.

Синтаксис:

template < параметры_шаблона >

определение_класса

В таком определении объявляется семейство классов. Параметры_шаблона, это обобщенные имена типов.

Отличие от шаблонов функций

При объявлении объекта класса необходимо указать фактический параметр - имя типа в угловых скобках <>. Это необходимо для создания реального объекта, где фактическим параметром будет тип данных объекта класса.

Пример - шаблон класса "массив". Тип элементов массива может быть любой, в том числе, отличный от базовых типов.

Механизм шаблона классов

При создании объекта класса определяется, объект какого именно класса, порожденного из шаблона, будет создан.

Это достигается подстановкой фактических параметров шаблона:

имя_класса <фактические_параметры> имя_объекта(м.быть_параметры_конструктора)

Например, My_Class <int> A (10);

Замечания и выводы

1. Параметр шаблона фактически заменяет произвольный тип. При формальном описании класса параметр шаблона используется как обобщенное имя типа.

Механизм: Шаблоны автоматически расширяются компилятором до полного описания классов.

array <int> c(20);

array <float> f(20);

2. Функции класса, объявленные и описанные внутри, являются inline.

Эти объявления можно перенести вне тела шаблона, тогда используется полное объявление шаблона функции, например:

template <class Type> Type имя_класса <Type>::имя_функции(...)

{

тело функции;

}

Дополнительно "имя_класса <Type>" - параметр шаблона.

3. Совпадение сигнатуры и перегрузка.

Родовая функция не может работать в специальных случаях. Например, Swap для базовых типов реализуется элементарно, для строк - иначе, для данных, являющихся объектами классов - иначе.

В этом случае используется перегрузка функции (или операции) для данного нестандартного типа. Допускается перегрузка по типу параметров и по типу функции.

Например, Swap для обмена значений двух строк будет выглядеть так:

void Swap ( char *s1,char *s2)

{

int len = (strlen(s1)>=strlen(s2)) ? strlen (s1): strlen (s2);

char *tmp = new char [len+1];

strcpy(tmp,s1);

strcpy(s1,s2);

strcpy(s2,tmp);

delete tmp;

}

4.Перегрузка операций для шаблонов.

Хочется воспользоваться готовыми шаблонами, применяя их к новым типам данных.

Например, Swap успешно переменяет местами данные базовых типов, и, возможно, данные производных типов, потому что конструктор копирования существует по умолчанию.

Сортировка для массива объектов требует:

Использовать операцию отношения < или > для сравнения объектов.

Использовать операцию = для присваивания нулю.

Во многих случаях требуется также перегружать конструктор копирования.

Вывод - если шаблон того требует, то операции перегружают.

My_class A,B;

// Прямое копирование.

A = B;

My_class *A = new My_Class; //

My_class *B = new My_Class;

// Поверхнстное копирование.

A = B;

5. Шаблоны классов могут содержать друзей.

friend функция, не использующая спецификацию шаблона, будет дружественной для всех экземпляров шаблона класса.

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

Например,

template <class T>

class Matrix { // Шаблон матрицы типа Т.

…

friend void norma (); // Универсальная функция.

…

friend Vector <T> Sum (Vector <T> V); // Экземпляр для класса.

…

} // End of Matrix

Прочие особенности дружественных функций сохраняются.

6. Статические элементы не универсальны, а являются собственными данными для каждой реализации объекта.

Например,

template <class Type> class F

{

public:

static int count;

...

};

// Инициализация статического данного

template <class Type> int F::count = 0;

Type <int> A;

Type <char> B;

Определены две статические переменные F <int>::count и F <char>::count.

template <class Type> class F

{

static int i; // Обычное статическое данное.

static Type t; // Параметризованное данное.

...

};

// Определить статическое данное:

template <class Type> int A <Type>::i=0;

template <class Type> Type B <Type>::t=0;

Type <char> A; // Имеет int A::i и char A::t;

Type <float> B; // Имеет int B::i и float B::t;

7. Число аргументов шаблона (функции или класса) не ограничено, типы могут быть различны.

Пример - можно параметризировать тип элементов массива и число данных в нем:

template <int n, class T> class Array

{

public:

T a[n];

...

};

Array <50,double> x,y;

...

x = y; // Должно работать.

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

8. Наследование.

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

Пример Template_class консольный.