Студопедия
Новини освіти і науки:
МАРК РЕГНЕРУС ДОСЛІДЖЕННЯ: Наскільки відрізняються діти, які виросли в одностатевих союзах


РЕЗОЛЮЦІЯ: Громадського обговорення навчальної програми статевого виховання


ЧОМУ ФОНД ОЛЕНИ ПІНЧУК І МОЗ УКРАЇНИ ПРОПАГУЮТЬ "СЕКСУАЛЬНІ УРОКИ"


ЕКЗИСТЕНЦІЙНО-ПСИХОЛОГІЧНІ ОСНОВИ ПОРУШЕННЯ СТАТЕВОЇ ІДЕНТИЧНОСТІ ПІДЛІТКІВ


Батьківський, громадянський рух в Україні закликає МОН зупинити тотальну сексуалізацію дітей і підлітків


Відкрите звернення Міністру освіти й науки України - Гриневич Лілії Михайлівні


Представництво українського жіноцтва в ООН: низький рівень культури спілкування в соціальних мережах


Гендерна антидискримінаційна експертиза може зробити нас моральними рабами


ЛІВИЙ МАРКСИЗМ У НОВИХ ПІДРУЧНИКАХ ДЛЯ ШКОЛЯРІВ


ВІДКРИТА ЗАЯВА на підтримку позиції Ганни Турчинової та права кожної людини на свободу думки, світогляду та вираження поглядів



Контакти
 


Тлумачний словник
Авто
Автоматизація
Архітектура
Астрономія
Аудит
Біологія
Будівництво
Бухгалтерія
Винахідництво
Виробництво
Військова справа
Генетика
Географія
Геологія
Господарство
Держава
Дім
Екологія
Економетрика
Економіка
Електроніка
Журналістика та ЗМІ
Зв'язок
Іноземні мови
Інформатика
Історія
Комп'ютери
Креслення
Кулінарія
Культура
Лексикологія
Література
Логіка
Маркетинг
Математика
Машинобудування
Медицина
Менеджмент
Метали і Зварювання
Механіка
Мистецтво
Музика
Населення
Освіта
Охорона безпеки життя
Охорона Праці
Педагогіка
Політика
Право
Програмування
Промисловість
Психологія
Радіо
Регилия
Соціологія
Спорт
Стандартизація
Технології
Торгівля
Туризм
Фізика
Фізіологія
Філософія
Фінанси
Хімія
Юриспунденкция






Шаблони, шаблони-класи

У мові С++ можливе і параметричне програмування (програмування з використанням родових компонентів). Родові (параметризовані) компоненти мають властивість адаптуватися до конкретної ситуації, в якій такий компонент використовується. Це дозволяє розробляти достатньо універсальні, водночас високоефективні компоненти програм (зокрема, об’єкти).

Параметричне програмування у мові С++ реалізоване за допомогою шаблонів (template). У С++ визначено два види шаблонів: шаблони-класи та шаблони-функції.

Шаблони-класи можуть використовуватись різними способами, але найбільш очевидним є їх використання в якості адаптивних об’єктів пам’яті. Щоб навести найпростіший приклад, припустимо, що потрібно визначити об’єкти, які можуть зберігати по два значення, одне ціле, а інше символьне. Для цього ми могли б визначити

class pair … int … char {

public:

int first;

char second;

pair … int … char(int x, char y):first(x), second(y) {}

};

Після цього ми могли б написати, наприклад,

pair … int … char pair1(13,`a’);

cout<< pair1.first<< end1;

cout<< pair1.second<< end1;

Якщо, крім цього, нам потрібні об’єкти, які можуть зберігати, скажімо, бульове значення та число подвійної точності, ми могли б визначити

class pair … bool … double {

public:

bool first;

double second;

pair … bool … double(bool x, double y): first(x), second(y) {}

};

і написати, наприклад:

pair … bool … double pair1 (true, 0.1);

cout<< pair1.first<< end1;

cout<< pair1.second<< end1;

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

template <class T1, class T2>

class pair {

public:

T1 first;

T2 second;

pair (T1 x, T2 y):first (x), second (y) {}

};

Останнє визначення класу написане з використанням двох імен довільних типів Т1 та Т2, які є типами-параметрами. Ці імена вводяться визначенням типів-параметрів за допомогою конструкції template <class T1, class T2>, яка означає, що можна подавати фактичні імена типів замість Т1 та Т2, отримує контрастний екземпляр шаблона-класу pair. Наприклад, конструкції

pair <int, char> pair3 (13, ‘a’);

pair <bool, double> part4 (true, 0.1);

оголошують об’єкти pair3 та pair4, які структурно тотожні об’єктам pair1 та pair2 відповідно.

Але тепер можна використати pair у незчисленній множині інших випадків з іншими комбінаціями фактичних типів, як наприклад

pair <double, long > pair5 (3.1415, 999);

pair <bool, bool > pair6 (false, true);

Як фактичні типи можуть використовуватися типи, визначені через інші класи; наприклад

pair <pair … int … char, float > pair7 (pair1, 1.23);

чи, що еквівалентно,

pair <pair<int, char>, float > pair8(pair3, 1.23);

Як показано тут, можна використовувати типи, які одержані як примірники (представники) шаблонів-класів, всюди, де можна використовувати звичайні типи.

Визначення шаблона-класу pair є дуже простим прикладом параметричного контейнерного класу; проте його можна адаптувати до багатьох різних застосувань. Звичайне перетворення звичайного класу на параметризований (оскільки воно знаходить застосування в найширшому класі прикладних програм) більш корисне, ніж просто додавання ключового слова template та списку параметрів типів. Можуть бути корисними деякі модифікації, щоб бути впевненим у тім, що результуючі примірники об’єктів так само ефективні, як і об’єкти, визначені звичайним способом, незалежно від того, які типи фактично будуть підставлені. У разі, коли визначення шаблона-класу таке просте, як pair, то можна зробити поліпшення. Визначення шаблона-класу було дуже простим:

pair (T1 x, T2 y);

Проблема в тому, що х та у передаються за значенням. Це означає, що якщо ці об’єкти великі, то при виклику конструктора будуть робитися їх додаткові копії, а це дорого коштує. Щоб уникнути цього, потрібно передавати х та у як константні посилальні параметри, щоб передавалися лише адреси. Саме таким чином визначається pair в STL:

template <class T1, class T2>

class pair {

public:

T1 first;

T2 second;

pair (T1& x, T2& y):first (x), second (y) {}

};

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

Шаблони-функції можуть використовуватися для визначення параметризованих алгоритмів. Простим прикладом є функція для визначення максимального із двох цілих:

int intmax (int x, int y)

{

return x<y?y:x;

}

Вона може визначити максимальне тільки із двох цілих (int), але її легко узагальнити, перетворивши на шаблон-функцію:

template <class T>

T max(T x, T y)

{

return x < y ? y : x;

}

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

int u = 3, v = 4;

double d = 4.7;

cout << max(u, v) << endl; //мається на увазі тип int

cout << max(d, 9.3) << endl; //мається на увазі тип double

cout << max(u, d) << endl; //помилка: невідповідність типів

Компілятор потребує, щоб через х та у передавалися значення однакових типів, оскільки в шаблоні для них було вказано один і той самий тип Т. Потрібно також, щоб було визначення операції < у вигляді списку її параметрів (Т, Т). Наприклад, повертаючись до використання шаблона-класу pair, визначеного в попередньому пунктi,

pair <double, long> pair 5(3.1415, 999);

компілятор видає помилку при компіляції оператора:

max (pair 5, pair 5);

через відсутність визначення операції operator < для об’єктів типу pair<double, long>. Але він буде компілювати, якщо попередньо ви­значити зміст операції operator < для об’єктів цього типу, наприклад:

pair <double, long> operator< (const pair <double, long)& x, const pair <double, long>& y)

//порівняти х та у за їх першими членами:

{

return x.first <y.first;

}

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

У висновку визначимо, що наведене визначення шаблона-функ­ції max може бути поліпшене так само, як це було зроблено для конструктора шаблона-класу pair, тобто введенням константних посилальних параметрів:

template <class T>

T max(const T& x, const T& y)

{

return x < y ? y : x;

}

Саме таке визначення використовується в STL.

Шаблони-функції як функції-члени

У визначенні звичайних класів чи шаблонів-класів функції-члени можуть мати шаблони в якості параметрів (у доповнення до шаблонів, які є параметрами класів). Ця нова властивість мови С++ використовується в шаблонах-класах при визначенні уміщуючих класів (контейнерів) STL. Наприклад, кожний уміщуючий клас має функцію-член insert, у якій є шаблон-параметр для визначення типу використовуваного ітератора:

template <class T>

сlass vector {

...

template <class Iterator >

insert(Iterator first, Iterator last);

...

};

Як буде показано далі, ця функція-член insert може використовуватися для того, щоб вставити елементи, які скопіювали з деякої іншої структури (наприклад, списку), використовуючи зв’язані з цією структурою ітератори. Визначення такої функції-члена як шаблона-функції, котрий має тип ітератора як параметра шаблона, робить її більш корисною, ніж коли б тип ітератора був у неї фіксований.

На жаль, надалі велика частина компіляторів С++ не підтримує функції-члени, які є шаблонами, що обмежує можливості STL.




Переглядів: 1790

<== попередня сторінка | наступна сторінка ==>
Реалізація залежностей | Параметри шаблонів, що опускаються

Не знайшли потрібну інформацію? Скористайтесь пошуком google:

 

© studopedia.com.ua При використанні або копіюванні матеріалів пряме посилання на сайт обов'язкове.


Генерація сторінки за: 0.004 сек.