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

4.7 Узагальнені функції (function template)

Узагальнені функції (function template)

Інший спосіб наділення однієї функції багатьма реалізаціями полягає у застосуванні узагальнених (generic) функцій. Для цього в С++ використовують так званий механізм шаблонів (template).

Розглянемо, наприклад, функцію swap, визначену нами для цілих чисел. При необхідності ми могли б довизначати її для інших типів, наприклад, дійсних чисел

void rswap( double &x, double &y)

{

double z = x; x=y; y=z;

}

При цьому легко помітити, що дії, які виконуються у функції, не залежать від типів її параметрів. На місці double міг би бути довільний тип, для якого визначена операція присвоєння. Ми могли б уявити собі таке параметричне визначення функції

void rswap( Type &x, Type &y)

{

Type z = x; x=y; y=z;

}

Тепер, правда, в програмі з’явився невизначений об’єкт Type. Залишилося сказати, що це довільний тип. Такого вигляду набуде повне визначення узагальненої функції

template <class Type>

void rswap( Type &x, Type &y)

{

Type z = x; x=y; y=z;

}

Узагальнені функції обробляються компілятором у дуже спеціальний спосіб. Компілятор не в стані побудувати об’єктний код, тому що різні типи даних можуть вимагати різних машинних команд для виконання однієї й тієї ж дії, хоч би й присвоєння. У випадку символу, це буде пересилка одного байту, для цілого — слова, для дійсного подвоєної точності — двох слів. Тому компілятор лише фіксує факт наявності шаблону, створюючи його конкретизації для кожного виклику. Так в контексті

char a, b;

rswap(a, b);

буде згенеровано об’єктний код для перестановки символів, а в контексті

float a, b;

rswap(a, b);

код для перестановки дійсних чисел. Або навіть

Point u, v;

rswap(u, v);

Шаблони можуть накладати певні обмеження на допустиму конкретизації. Якщо ми повернемося до прикладу з максимумом, то одержимо шаблон

template <class Type> Type max(Type x, Type y)

{

return (x>y? x: y);

}

Тут Type вже не будь-який тип, а лише такий, для якого визначено порівняння на нерівність. Компілятор не зможе згенерувати коду для спроби обчислити максимум двох точок

Point u, v, w;

w = max(u, v);

Інша проблема узагальнених функцій викликана складностями з перетворенням типів. Дійсно, один і той же типовий параметр, наприклад, T з попереднього прикладу не може набувати одного значення на місці першого аргументу і іншого на другому місці. Ось приклад, який показує проблеми і шляхи їх вирішення

template <class T> T mymax (T x, T y)

{

cout<<"template ";

return x>y? x: y;

};

Явна функція сильніша за узагальнену

long mymax(long x, long y)

{

cout<<"long ";

return x>y? x: y;

};

При необхідності змішувань типів доведеться користуватися додатковими специфікаціями

inline double mymax (int x, double y)

{

return mymax<double>((double)x, y);

};

Варіанти викликів

cout<<mymax(1,2)<<endl;

cout<<mymax('a','b')<<endl;

cout<<mymax(1l,3l)<<endl;

cout<<mymax(1l,4)<<endl; // error

cout<<mymax<long>(1,5)<<endl; // узагальнена

cout<<mymax<long>(1l,5)<<endl; // явна

cout<<mymax(1,3.14)<<endl;

cout<<mymax(1l,4.14)<<endl;

cout<<mymax('a',1)<<endl; // error