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

Параметрический полиморфизм

План

1. Обобщенная идея.

2. Шаблоны функций. Классический С++.

3. Шаблоны классов. Классический С++.

4. Родовые объекты. Управляемый С++/CLI.

5. Примеры типов – шаблонов в Net.Framework.

1. Обобщенная идея

Много алгоритмов, которые применимы к разным типам данных.

Перегрузка функций – решение проблем.

Введение

Функция или тип являются параметризованными, когда один или несколько типов, используемых в определении, являются неопределенными. Используя эту функцию или тип, пользователь может по своему усмотрению подставлять требуемые типы данных при обращении к функции или порождении объекта класса.

Пример

class My_Object

{

...

}

void Swap (int &x, int &y)

{

int buf = x;

x = y;

y = buf;

}

void Swap (My_Object &x, My_Object &y)

{

My_Object buf = x;

x = y;

y = buf;

}

Эти функции отличаются только типом параметров, который можно объявить обобщенным именем, например:

void Swap (Type &x, Type &y)

{

Type buf = x;

x = y;

y = buf;

}

Параметром является имя типа, названное обобщенным именем Type – имя любого типа.

При обращении к функции на место параметров с указанным именем можно передавать данные произвольных типов, в том числе, базовых, или конструируемых, в том числе классов.

Ограничения для производных типов.

К параметризованным типам относятся

1. Шаблоны, унаследованные от С++.

2. Родовые (общие) объекты, которые являются параметризованными типами CLI/C++.

1.1. Шаблоны функций

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

Примеры: поиск, сортировка, суммирование и похожие алгоритмы, как правило, применяются к последовательности (совокупности, коллекции) данных.

Пример. Поиск

а) в одномерном массиве целых чисел.

Для поиска необходимо выполнять операцию сравнения a[i] с образцом.

a[i]==Целое_число

б) в массиве строк

Для поиска необходимо выполнять операцию сравнения строки с образцом.

cmpstr(строка_1, строка_2)

в) в массиве записей

Для поиска необходимо выполнять операцию сравнения данного произвольного типа с образцом.

Сидоров Сидор 180 90

Петров Петр 200 100

Козлов Казимир 180 60

1) по фамилии

2) по имени

3) по фамилии и имени

4) по прочим данным

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

Qsort (указатель_на_массив, число_эл-тов, размер_элемента,

указатель_на_функцию_сравнения_элементов);

Дополнительно к имени массива функция должна получить параметры:

1) размер_элемента;

2) указатель_на_функцию_сравнения_элементов. Такая функция должна уметь сравнить данные передаваемого типа и вернуть логическое значение, потому что в любом алгоритме сортировки необходимо сравнить данные и переместить их.

int Relation ()

{

return a[i]<образец;

}

int Relation ()

{

return cmpstr(a[i],образец);

}

int < int

float < float

char * < * char

Объект_1 < Объект_2

и так далее.

Это неудобно, хотя возможно.

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

Можно отнести к параметрам (параметризировать):

1) тип возвращаемого значения;

2) типы параметров функции (при фиксированных числе и порядке);

3) локальные данные функции.

Синтаксис шаблона функции (присутствует ключевое слово template)

template <список_параметров_шаблона> тип_функции имя_функции (параметры_с_указанием_типа)

{

тело - определение функции;

}

Сравнить с обычным описанием функции.

Что можно параметризировать?

1. Тип данных.

2. Тип функции.

Важно: Сигнатура параметров одинакова.

Требования

1. Список формальных параметров шаблона указан в угловых скобках < >, и это обобщенное имя типа данного.

2. Каждый формальный параметр шаблона обозначается служебным словом class, за которым следует имя параметра (абстрактное имя типа).

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

Пример - шаблон функций Swap для обмена двух значений.

template <class Type> void Swap (Type &x, Type &y)

{

Type buf = x;

x = y;

y = buf;

}

Здесь Type - параметр шаблона функции, используется:

а) в заголовке для спецификации формальных параметров;

б) в теле шаблона для объявления локальной переменной;

в) может объявлять тип функции.

Механизм шаблона функции

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

Например, если в программе объявлены:

float a,b;

a=2.3;

b=7.9;

, то для обращения

Swap(a,b);

будет генерирован код:

void Swap (float & x, float & y)

{

float z = x;

x = y;

y = z;

}

, и далее выполнено обращение именно к этой функции.

Для переменных другого типа генерируется другой код функции.

Замечание

Для обычных данных использование шаблона не имеет особенностей.

Для объектов класса есть особенности:

  1. конструктор копирования копирует не объект, а его адрес (поверхностное копирование);

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

Примеры в консольном Template.

1. Шаблон функции Swap.

  • Для простых типов.

  • Для строк.

  • Для объектов класса.

2. Пример шаблонов функций обработки массива для поиска максимума в массивах разных типов.

  • Для простых типов.

  • Для объектов класса.