Скачиваний:
42
Добавлен:
15.06.2014
Размер:
527.87 Кб
Скачать

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 комплексных чисел