МАРК РЕГНЕРУС ДОСЛІДЖЕННЯ: Наскільки відрізняються діти, які виросли в одностатевих союзах
РЕЗОЛЮЦІЯ: Громадського обговорення навчальної програми статевого виховання ЧОМУ ФОНД ОЛЕНИ ПІНЧУК І МОЗ УКРАЇНИ ПРОПАГУЮТЬ "СЕКСУАЛЬНІ УРОКИ" ЕКЗИСТЕНЦІЙНО-ПСИХОЛОГІЧНІ ОСНОВИ ПОРУШЕННЯ СТАТЕВОЇ ІДЕНТИЧНОСТІ ПІДЛІТКІВ Батьківський, громадянський рух в Україні закликає МОН зупинити тотальну сексуалізацію дітей і підлітків Відкрите звернення Міністру освіти й науки України - Гриневич Лілії Михайлівні Представництво українського жіноцтва в ООН: низький рівень культури спілкування в соціальних мережах Гендерна антидискримінаційна експертиза може зробити нас моральними рабами ЛІВИЙ МАРКСИЗМ У НОВИХ ПІДРУЧНИКАХ ДЛЯ ШКОЛЯРІВ ВІДКРИТА ЗАЯВА на підтримку позиції Ганни Турчинової та права кожної людини на свободу думки, світогляду та вираження поглядів Контакти
Тлумачний словник |
|
|||||||
Шаблони, шаблони-класиУ мові С++ можливе і параметричне програмування (програмування з використанням родових компонентів). Родові (параметризовані) компоненти мають властивість адаптуватися до конкретної ситуації, в якій такий компонент використовується. Це дозволяє розробляти достатньо універсальні, водночас високоефективні компоненти програм (зокрема, об’єкти). Параметричне програмування у мові С++ реалізоване за допомогою шаблонів (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.
|
||||||||
|