- •7. Робота з шаблонними, функціями та класами
- •7.1. Поняття про узагальнені функції
- •7.1.1. Механізм реалізації шаблонної функції з одним узагальненим типом
- •7.1.2. Безпосередньо задане перевизначення узагальненої функції
- •7.1.3. Шаблонна функція з двома узагальненими типами
- •7.1.4. Механізм перевизначення специфікації шаблону функції
- •7.1.5. Використання стандартних параметрів у шаблонних функціях
- •7.1.6. Обмеження, які застосовуються при використанні узагальнених функцій
- •7.1.7. Приклад створення узагальненої функції abs()
- •7.2. Поняття про узагальнені класи
- •7.2.1. Створення класу з одним узагальненим типом даних
- •7.2.2. Створення класу з двома узагальненими типами даних
- •7.2.3. Приклад створення узагальненого класу для організації безпечного масиву
- •7.2.4. Використання в узагальнених класах аргументів, що не є узагальненими типами
- •11.2.1. Передача покажчиком на функцію її адреси іншій функції
- •9.2.3. Класи потоків
- •9.3. Особливості механізмів перевизначення операторів введення-виведення даних
- •9.3.1. Створення перевизначених операторів виведення даних
- •9.5. Організація файлового введення-виведення даних
- •9.5.1. Відкриття та закриття файлу
- •9.5.2. Зчитування та запис текстових файлів
- •9.5.3. Неформатне введення-виведення даних у двійковому режимі
- •9.5.4. Зчитування та записування у файл блоків даних
- •10. Динамічна ідентифікація типів і оператори приведення типу
- •10.1. Динамічна ідентифікація типів
- •10.1.1. Отримання типу об'єкта у процесі виконання програми
- •10.1.2. Приклад rtti-застосування
- •11. Поняття про простори імен та інші ефективні програмні засоби
- •11.1. Особливості організації простору імен
- •11.1.1. Поняття про простори імен
- •11.1.2. Застосування настанови using
- •11.1.3. Неіменовані простори імен
- •11.1.4. Застосування простору імен std
- •11.2. Застосування покажчиків на функції
- •11.2.2. Пошук адреси перевизначеної функції
- •11.3. Поняття про статичні члени-даних класу
- •11.5. Застосування до функцій-членів класу модифікаторів const і mutable
- •11.6. Використання explicit-конструкторів
- •12. Введення в стандартну бібліотеку шаблонів
- •12.1. Огляд стандартної бібліотеки шаблонів
- •12.2. Поняття про контейнерні класи
- •12.3. Механізми роботи з векторами
- •12.3.1. Доступ до елементів вектора за допомогою ітератора
- •12.3.2. Вставлення та видалення елементів з вектора
- •12.3.3. Збереження у векторі об'єктів класу
- •12.3.4. Доцільність використання ітераторів
- •7. Робота з шаблонними, функціями та класами 1
- •7.1. Поняття про узагальнені функції 1
- •10. Динамічна ідентифікація типів і оператори приведення типу 26
- •11. Поняття про простори імен та інші ефективні програмні засоби 31
- •12. Введення в стандартну бібліотеку шаблонів 44
7.1.2. Безпосередньо задане перевизначення узагальненої функції
Незважаючи на те, що узагальнена функція сама перевизначається в міру потреби, однак це можна робити і безпосередньо. Формально цей процес називається безпосередньою спеціалізацією. При перевизначенні узагальнена функція пере визначається "на вигоду" цієї конкретної версії. Розглянемо, наприклад, наведену нижче програму, яка є переробленою версію першого прикладу з цього розділу.
"Вручну" перевизначена версія узагальненої функції називається епон середньою спеціалізацією.
Демонстрація механізму перевизначення шаблонної функції
#include <vcl>
#include <iostream> // Для потокового введення-виведення
#include <conio> // Для консольного режиму роботи
using namespace std; // Використання стандартного простору імен
template <class aType> void swapAB(aType &a, aType &b)
{
aType tmp; // Створення тимчасової змінної
tmp = a;
a = b;
b = tmp;
cout << "Виконується шаблонна функція swapAB" << endl;
}
// Ця функція перевизначає узагальнену версію функції swapAB() для int-параметрів. void swapAB(int &a, int &b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
cout << "Це int-спеціалізація функції swapAB" << endl;
}
int main()
{
int i = 10, j = 20;
double x = 10.1, y = 23.3;
char a = 'x', b = 'z';
cout << "Початкові значення i, j: " << i << " " << j << endl;
cout << "Початкові значення x, y: " << x << " " << y << endl;
cout << "Початкові значення a, b: " << a << " " << b << endl;
swapAB(i, j); // Викликається безпосередньо перевизначена функція swapAB().
swapAB(x, y); // Викликається узагальнена функція swapAB().
swapAB(a, b); // Викликається узагальнена функція swapAB().
cout << "Після перестановки i, j: " << i << " " << j << endl;
cout << "Після перестановки x, y: " << x << " " << y << endl;
cout << "Після перестановки a, b: " << a << " " << b << endl;
getch(); return 0;
}
Внаслідок виконання ця програма відображає на екрані такі результати:
Початкові значення i, j: 10 20
Початкові значення x, у: 10.1 23.3
Початкові значення a, b: x z
Це int-спеціалізація функції swapAB.
Виконується шаблонна функція swapAB.
Виконується шаблонна функція swapAB.
Після перестановки i, j: 20 10
Після перестановки x, у: 23.3 10.1
Після перестановки a, b: z x
Як зазначено в коментарях до цієї програми, під час виклику функції swapAB(i,j) виконується безпосередньо перевизначена версія функції swapAB(), яку визначено у програмі. Компілятор у цьому випадку не генерує узагальнену функцію swapAB(), оскільки вона перевизначається безпосередньо заданим варіантом перевизначеної функції. Для позначення безпосередньої спеціалізації функції можна використовувати новий альтернативний синтаксис, що містить ключове слово template. Наприклад, якщо задати спеціалізацію з використанням цього альтернативного синтаксису, то перевизначена версія функції swapAB() з попереднього коду програми виглядатиме так:
// Використання нового синтаксису задавання спеціалізації
template<> void swapAB<int>(int &a, int &b)
{
int tmp;
tmp = a;
a = b;
b = tmp;
cout << "Це int-спеціалізація функції swapAB" << endl;
}
Як бачите, в новому синтаксисі для позначення спеціалізації використовують конструкцію template<>. Тип даних, для яких створюється ця спеціалізація, вказується в кутових дужках після імені функції. Для задавання будь-якого типу узагальненої функції використовується один і той самий синтаксис. На даний момент жоден з синтаксичних способів задавання спеціалізації не має жодних переваг перед іншим, але з погляду перспективи розвитку мови програмування, можливо, все ж таки краще використовувати новий стиль.
Безпосередня спеціалізація шаблону дає змогу спроектувати версію узагальненої функції з розрахунку на деяку унікальну ситуацію, щоб, можливо, скористатися перевагами підвищеної швидкодії програми тільки для одного типу даних. Але, як правило, якщо виникає потреба мати різні версії функції для різних типів даних, то доцільно використовувати перевизначені функції, а не шаблони.
