
Лекции по ППВиС (17 шт, ppt) Романов ВИ 2011 1ый семестр / Л9_Шаблоны
.ppt
1
Шаблоны
В языке С++ есть еще один вид полиморфизма, который носит название статического полиморфизма и представляется через механизм шаблонов (templates). Шаблоны используются для создания параметризованных типов (обычно классов) и
параметризованных функций.
Итак, два вида шаблонов – шаблоны функций и шаблоны классов.
Можно написать функцию и, в зависимости от аргументов,
будет обеспечено исполнение того или иного тела функции. А что, если в роли аргументов функции мы хотим видеть тип данных?
Раньше с такой целью использовались макросы. Именно с

2
Шаблоны функций – пример потребности
#include <iostream> using namespace std;
void print(int *array,int d) |
|
|
|
{ |
for (int i=0; i < d; cout << array[i],i++); |
cout << endl; |
} |
void print(char *array,int d) |
|
|
|
{ |
for (int i=0; i < d; cout << array[i],i++); |
cout << endl; |
} |
void main()
{
char *a1 ="Thing!";
int a2[5] = {1,2,3,4,5}; print (a1,6);
print (a2,5); char s; cin >> s;
}

3
Применение макросов
#include <iostream> using namespace std;
#define PRN(Type,arr,d) \
{ for (int i=0; i < d; cout << (Type)arr[i], i++); cout << endl; }
void main() |
|
|
{ |
|
|
char *a1 ="Thing!"; |
|
|
int a2[5] = {1,2,3,4,5}; |
|
|
PRN(char, a1, 6); |
// |
print (a1,6); |
PRN(int, a2, 5); |
// |
print (a2,5); |
char s; cin >> s;
}

4
Шаблоны функций
Шаблоны функций являются логическим продолжением механизма перегрузки функций. Обычно перегрузку функций осуществляют для различных типов данных, причем все перегруженные функции осуществляют идентичные действия. Например, для сортировки и вывода на экран одномерных массивов данных различных типов, приходится реализовывать различные перегруженные функции, содержимое которых порой отличается только используемыми типами данных. Так для возможности сортировки массивов int* и char* приходится реализовывать две перегруженные функции sort(int*, int) и sort(char*, int).
Механизм шаблонов в С++ позволяет решить эту проблему более удобным способом. Достаточно описать один шаблон, а компилятор сгенерирует код такой функции в соответствии использованному типу данных при вызове такой функции.

5
Шаблоны функций – определение
Шаблон функции задается следующим образом:
template <class тип_параметра> возвращаемый_тип имя_функции (аргументы)
{ . . . }
Определение каждого типа параметра начинается с ключевого слова class. Если функция использует более одного типа, то все они перечисляются через запятую. При компиляции компилятор вместо типа параметра подставляет необходимый тип, который был задан при вызове функции.
В качестве типа параметра могут быть заданы не только встроенные типы, но и типы, определенные пользователем, в том
числе и классы.

6
Шаблоны функций – определение дополнительно
Синтаксис шаблона должен повторяться как при объявлении, так и при определении функции.
Помните, шаблоны на самом деле являются макросами, поэтому они должны находиться в файлах .h. Если определение будет находиться в файле .срр, то в других .cpp-файлах нашей программы шаблон будет недоступен и программа работать не будет.
// Объявление функции |
// Определение ее |
реализации |
|
template <class Type> |
template <class Type> |
Type* func(Type* t); |
Type* func(Type* t) { |
|
// Тело функции, в котором |
|
имя |
|
// Type используется в |
// Вызов параметризированной функциикачестве |
|
Obj* f = func<Obj>(new Obj); |
// параметра макроса |
//Определение генерируется компилятором}
// при необходимости, то есть при вызове функции.

7
Шаблоны функций – пример
Для нашего примера можем определить:
template <class Array_Type> void print (Array_Type * array, int d) { for (int i=0; i < d; cout << array[i],i++); cout << endl; }
И тогда void main()
{
char *a1 ="Thing!";
int a2[5] = {1,2,3,4,5};
long a3[3] = {0xffffeeee, 0xeeeeaaaa, 0xcccccccc} print (a1,6);
print (a2,5); print (a3,3); char s; cin >> s;
}

8
Шаблоны функций – еще пример
#include <iostream> using namespace std;
class Integer { int n;
public:
Integer(int n=0) { this->n = n; } int get() { return n; }
};
class String { char * str;
public:
String(char *str="No") { this->str = str; }
char * get() { return str; }
};
template <class Class_Type> void print_info (Class_Type obj)
{
cout << obj.get() << endl;
}
void main()
{
Integer Num(12); String buf; print_info (Num); print_info (buf);
char s; cin >> s;
}

9
Шаблоны функций – дополнительно
Шаблоны функций могут быть перегружены.
Если в шаблоне описаны несколько типов параметров, то они все должны быть обязательно описаны в списке аргументов функции.
template <class Class_Type1, class Class_Type2> void print_info (Class_Type1 obj1, Class_Type2 obj2)
{
cout << " Obj1 = " << obj1.get() << endl; cout << " Obj2 = " << obj2.get() << endl;
} |
|
|
void main() |
Результаты: |
|
{ |
||
|
||
Integer Num(12); String buf; |
|
|
print_info (Num, buf); cout << endl; |
|
|
print_info (buf, Num); |
|
|
char s; cin >> s; |
|
|
} |
|

10
Определение шаблона класса
Идея параметризации классов та же – описывается шаблон класса, который осуществляет идентичные действия с различными типами данных. Используемый тип данных определяется на стадии компиляции.
Объявление параметризированного класса (шаблона): template <class тип>
объявление параметризируемого класса;
Тип является аргументом шаблона.
Экземпляр параметризированного класса описывается в виде:
имя_класса < тип > объект;
Варианты использования:
stack<char> stk_c; |
// стек на 1000 символов |
stack<char*> stk_str(200); // стек на 200 указателей
stack<complex> stk_cx(40); // стек на 40 комплексных чисел