- •7. Робота з шаблонними, функціями та класами
- •7.1. Поняття про узагальнені функції
- •7.1.1. Механізм реалізації шаблонної функції з одним узагальненим типом
- •7.1.2. Безпосередньо задане перевизначення узагальненої функції
- •7.1.3. Шаблонна функція з двома узагальненими типами
- •7.1.4. Механізм перевизначення специфікації шаблону функції
- •7.1.5. Використання стандартних параметрів у шаблонних функціях
- •7.2. Поняття про узагальнені класи
- •7.1.6. Обмеження, які застосовуються при використанні узагальнених функцій
- •7.1.7. Приклад створення узагальненої функції abs()
- •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.2.2. Створення класу з двома узагальненими типами даних
Шаблонний клас може мати декілька узагальнених типів даних. Для цього достатньо оголосити всі потрібні типи даних в template-специфікації у вигляді елементів списку, що розділяються між собою комами. Наприклад, у наведеному нижче коді програми створюється клас, який використовує два узагальнених типи даних.
Демонстрація механізму створення класу з двома узагальненими типами даних
#include <vcl>
#include <iostream> // Для потокового введення-виведення
#include <conio> // Для консольного режиму роботи
using namespace std; // Використання стандартного простору імен
template <class aType, class bType> class myClass {
aType c;
bType d;
public:
myClass(aType ObjA, bType ObjB) { c = ObjA; d = ObjB; }
void showType()
{cout << "c= " << c << "; d= " << d << endl; }
};
int main()
{
myClass<int, double> ObjA(10, 0.23);
myClass<char, char *> ObjB('x', "Це тест.");
ObjA.showType(); // Відображення int- і double-значень
ObjB.showType (); // Відображення значень типу char і char *
getch(); return 0;
}
Внаслідок виконання ця програма відображає на екрані такі результати:
c= 10; d= 0.23
c= x; d= Це тест.
У цьому коді програми оголошується два види об'єктів. Об'єкт ObjA використовує дані типу int і double, а об'єкт ObjB – символ і покажчик на символ. Для цих ситуацій компілятор автоматично генерує дані та функції відповідного способу побудови об'єктів.
7.2.3. Приклад створення узагальненого класу для організації безпечного масиву
Розглянемо ще одне застосування узагальненого класу. Як уже зазначалося вище, у процесі виконання програми, написаній мовою програмування C++, можливий вихід за межі масиву без видачі повідомлення про помилку. Але, якщо створити клас, який би містив масив, і дати змогу доступ до цього масиву тільки через перевизначений оператор індексації ("[]"), то можна перехопити індекс, що відповідає адресі за межами адресного простору масиву.
Об'єднавши перевизначення оператора з узагальненим класом, можна створити узагальнений тип безпечного масиву, який потім буде використано для створення безпечних масивів, призначених для зберігання даних будь-якого типу. Такий тип масиву і створюється в наведеному нижче коді програми.
Демонстрація механізму створення та використання узагальненого класу для організації безпечного масиву
#include <vcl>
#include <iostream> // Для потокового введення-виведення
#include <conio> // Для консольного режиму роботи
using namespace std; // Використання стандартного простору імен
const int size = 10;
template <class aType> class arrClass { // Оголошення класового типу
aType aMas[size];
public:
arrClass() { for(int i=0; i<size; i++) aMas[i] = i; }
arrClass &operator[](int i);
};
// Забезпечення контролю меж для класу aType.
template <class aType> aType &arrClass<aType>::operator[](int i)
{
if(i<0 || i> size-1) {
cout << "Значення індексу " << i << " за межами масиву" << endl;
exit(1);
}
return aMas[i];
}
int main()
{
arrClass<int> ObjI; // Масив int-значень
arrClass<double> ObjD; // Масив double-значень
cout << "Масив int-значень: ";
for(int i=0; i<size; i++) ObjI[i] = i;
for(int i=0; i<size; i++) cout << ObjI[i] << " ";
cout << endl;
cout << "Масив double-значень: ";
for(int i=0; i<size; i++) ObjD[i] = i/3.0;
for(int i=0; i<size; i++) cout << ObjD[i] << " ";
cout << endl;
ObjI[12] = 100; // Помилка, спроба вийти за межі масиву!
getch(); return 0;
}
Внаслідок виконання ця програма відображає на екрані такі результати:
Масив int-значень: 0 1 2 3 4 5 6 7 8 9
Масив double-значень: 0 0.333333 0.666667 1 1.333333 1.666667 2 2.333333 2.666667 3
У цьому коді програми спочатку створюється узагальнений тип безпечного масиву, а потім продемонстровано його використання шляхом побудови масиву цілих чисел і масиву double-значень. Було б непогано, якби Ви спробували створити масиви інших типів. Як доводить цей приклад, одна з великих переваг узагальнених класів полягає у тому, що вони дають змогу тільки один раз написати програмний код, відлагодити його, а потім застосовувати його до даних будь-якого типу, не переписуючи його для кожного конкретного застосування.
