Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
7
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

17.1.2. Шаблонна функція з двома узагальненими типами

У template-настанові можна визначити декілька узагальнених типів даних, використовуючи перелік елементів, розділених між собою комами. Наприклад, у наведеному нижче коді програми створюється шаблонна функція з двома узагальненими типами.

Код програми 17.1. Демонстрація механізму застосування шаблонної функції з двома узагальненими типами

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

template <class aType, class bType> void fun_c(aType a_ob, bType b_ob)

{

cout << a_ob << " " << b_ob << "\n";

}

int main()

{

fun_c(10, "Привіт");

fun_c(0.23, 10L);

getch(); return 0;

}

У наведеному прикладі у процесі виконання функції main(), коли компілятор генерує конкретні примірники функції fun_c(), заповнювачі типів aType і bType замінюються спочатку парою типів даних int і char *, а потім парою double і long відповідно.

Необхідно пам'ятати! Створюючи шаблонну функцію, програміст дає змогу компіляторові генерувати стільки різних версій цієї функції, скільки необхідно для оброблення різних типів даних, які використовує програма для її виклику.

17.1.3. Безпосередньо задане перевантаження узагальненої функції

"Вручну" перевантажена версія узагальненої функції називається безпосередньою спеціалізацією.

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

Код програми 17.2. Демонстрація механізму перевантаження шаблонної функції

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

template <class aType> void swapAB(aType &a_ob, aType &b_ob)

{

aType tmp; // Створення тимчасового об'єкта

tmp = a_ob;

a_ob = b_ob;

b_ob = tmp;

cout << "Виконується шаблонна функція swapAB.\n";

}

// Ця функція перевизначає узагальнену версію функції

// swapAB() для int-параметрів.

void swapAB(int &a, int &b)

{

int tmp;

tmp = a;

a = b;

b = tmp;

cout << "Це int-спеціалізація функції swapAB.\n";

}

int main()

{

int i = 10, j = 20;

double x = 10.1, y = 23.3;

char a = 'x', b = 'z';

cout << "Початкові значення i, j: " << i << " " << j << "\n";

cout << "Початкові значення x, y: " << x << " " << y << "\n";

cout << "Початкові значення а, b: " << a << " " << b << "\n";

swapAB(i, j); // Викликається безпосередньо перевантажена

// функція swapAB().

swapAB(x, y); // Викликається узагальнена функція swapAB().

swapAB(a, b); // Викликається узагальнена функція swapAB().

cout << "Після перестановки i, j: " << i << " " << j << "\n";

cout << "Після перестановки x, y: " << x << " " << y << "\n";

cout << "Після перестановки а, b: " << a << " " << b << "\n";

getch(); return 0;

}

У процесі виконання ця програма відображає на екрані такі результати:

Початкові значення i, j: 10 20

Початкові значення х, у: 10.1 23.3

Початкові значення а, b: x z

Це int-спеціалізація функції swapAB.

Виконується шаблонна функція swapAB.

Виконується шаблонна функція swapAB.

Після перестановки i, j: 20 10

Після перестановки х, у: 23.3 10.1

Після перестановки а, b: z x

Як зазначено в коментарях до цієї програми, під час виклику функції swapAB(i, j) виконується безпосередньо перевантажена версія функції swapAB(), яка є визначена у програмі. Компілятор у цьому випадку не генерує цю версію узагальненої функції swapAB(), оскільки узагальнена функція перевизначається безпосередньо заданим варіантом перевантаженої функції.

Для позначення безпосередньої спеціалізації функції можна використовувати новий альтернативний синтаксис, що містить ключове слово template. Наприклад, якщо задати спеціалізацію з використанням цього альтернативного синтаксису, то перевантажена версія функції swapAB() з попередньої програми виглядатиме так:

// Використання нового синтаксису задавання спеціалізації

template<> void swapAB<int>(int &a, int &b)

{

int tmp;

tmp = а;

a = b;

b = tmp;

cout << "Це int-спеціалізація функції swapAB.\n";

}

Як бачите, в новому синтаксисі для позначення спеціалізації використовують конструкцію template<>. Тип даних, для яких створюється ця спеціалізація, вказується в кутових дужках після імені функції. Для задавання будь-якого типу узагальненої функції викори­стовується один і той самий синтаксис. На даний момент жоден з синтаксичних способів задавання спеціалізації не має жодних переваг перед іншим, але з погляду перспективи розвитку мови програмування, можливо, все ж таки краще використовувати новий стиль.

Безпосередня спеціалізація шаблону дає змогу спроектувати версію узагальненої функції з розрахунку на деяку унікальну ситуацію, щоб, можливо, скористатися перевагами підвищеної швидкодії програми тільки для одного типу даних. Але, як правило, якщо виникає потреба мати різні версії функції для різних типів даних, то доцільно використовувати перевантажені функції, а не шаблони.