Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторні роботи по програмуванні(14 лаб).doc
Скачиваний:
77
Добавлен:
16.05.2015
Размер:
1.43 Mб
Скачать

Параметризовані класи

Визначаючи параметризований клас, ми створюємо його каркас(шаблон), що описує усі алгоритми, що використовуються класом. Фактичний тип даних, над яким проводитимуться маніпуляції, буде вказаний в якості параметру при конкретизації об'єктів цього класу. Компілятор автоматично згенерує відповідний об'єкт на основі вказаного типу. Загальна форма декларування параметризованого класу буде такою:

template <class Ttype> class class_name{

// протокольна частина класу }

Тип Ttype являє собою ім'я типу шаблону, яке в кожному випадку конкретизації буде замінюватися конкретним типом даних. При необхідності можливо визначити більше одного параметризованого типу даних, використовуючи їх список через кому. У межах визначення класу шаблонне ім'я можна використовувати у будь-якому місці. Для створення конкретної реалізації використовується наступна форма:

template <int size> // параметр шаблону є константа

class memo

{

public:

memo()

{

p=new char[size];

}~memo()

{

delete [] p; }

Створення представника такого класу можливо таким способом:

memo<constl> memorize;

Приклад 1. Створимо визначення класу із застосуванням в якості аргументу шаблону типового параметру. Приміром, створимо клас, що являє собою зв'язаний список об'єктів поки що невідомого типу даних:

template <class T> // параметр шаблону є константа

class stack {

/* клас включає в себе дані дня обходу списку та методи маніпуляції даними*/

public: T getdata(); stack *gertnext; private:

T data; stack *next; };

На основі вищевказаного опису можливе, приміром, наступним

чином створення списків різних типів: stack <int> intstsck; stack <double> dblstck;

При визначенні функцій-членів для шаблону теж потрібно використовувати template.

Список аргументів шаблону складається з ключового слова class та ідентифікатору (ів), що визначає його тип. Коли компілятор створюватиме конкретну версію цієї функції, він автоматично замінить цей параметр конкретним типом даних. Зручним є створення прототипу шаблона функції у вигляді його попереднього оголошення. Таке оголошення інформує компілятор про наявність шаблону та очікуваних параметрах, наприклад:

Template <classT> void funk(Tarray[],sizearray);

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

Приклад 1

template <class Swaptype> void swap(Swaptype &x, Swaptype &y)

{

Swaptype temp;

temp=x;

у=temp;

}

Щоб використати такий шаблон, можна оголосити такий прототип:

void swap (double a, double b);

Якби swap() була звичайною функцією, то потрібною була б її реалізація. Оскільки це шаблонна функція, компілятор сам реалізуватиме код такої функції, замінивши у даному випадку тип Swap на double. Таким чином можна зменшиш розмір та складність програми, запропонувавши компілятору реалізацію узагальнених функцій. Що стосується викликів таких функцій, то їх організація відбувається звичайним чином.

Приклад 2

/* функція сприймає масив невизначеного типу та два цілих числа, обмінюючи зміст елементів масиву із вказаними індексами на х та у*/ template <class T> void funk1(T t[], int x, int y}

{

T tmp=t[xJ;

t[x]=t[y];

t[y]=tmp;

}

Коректними будуть такі оголошення прототипів за цим шаблоном:

void funk1(char t[],int x,int y);

void funk1(int t[],int x,int y);

Таким чином, с можливість легко створювати нові функції, підставляючи в існуючі шаблони конкретні аргументи.

Щодо перевшггажеіяш шаблонів класу та функцій. В той час, як є можливим перевантаження імен шаблонів функцій, неможливим є цей процес для імен шаблонів класів. Наприклад, неможливо визначити одночасно Tarray<class T> ma Tarray<class T, int size), в той час як без проблем перевантажуються шаблони функцій. Адже ніщо не завадить описати декілька шаблонів функцій з одним і тим же ім'ям, якщо лише вони мають відмінне число або різний тип параметрів.

Класи потоків C++

Технологія потоків значно відрізняється від звичайних засобів вводу-виведення, які використовує Сі. Згадаймо відомі функції з традиційного Сі printf(), scanf() та численних їхніх "родичів", які не передбачають ніякої перевірки типу, потребуючи від програміста чіткого дотриманні правил застосування аргументів, символів форматування тощо. Компілятор в такому випадку не в змозі сигналізувати про невідповідність специфікацій формату прийнятим фактичним аргументам, а тому цілком покладає що відповідальність на користувача, що на практиці нерідко закінчується помилкою виконання. Використання класів потоків настільки спрощене, що контроль за співпаданням кількості та типів аргументів перекладається на компілятор.