67353

Шаблони. Узагальнені функції

Лекция

Информатика, кибернетика и программирование

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

Украинкский

2014-09-07

96.5 KB

0 чел.

Лекція № 19

Тема: Шаблони. Узагальнені функції

План

  1.  Поняття про шаблони
  2.  Поняття про узагальнені функції
  3.  Шаблонна функція з одним узагальненим типом
  4.  Безпосередньо задане перевантаження узагальненої функції
  5.  Шаблонна функція з двома узагальненими типами

  1.  Поняття про шаблони

    Шаблон – це один із складних і потужних засобів мови програмування C++. Він не увійшов до початкової специфікації мови C++, і тільки в кінці 90-х років став невід'ємною частиною програмування нею. Шаблони дають змогу виконати одне з найважчих завдань у програмуванні – створювати програмний код, який можна використовувати для оброблення різних типів даних.

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

  1.   Поняття про узагальнені функції

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

сиву чисел з плинною крапкою. Відмінність тут полягає тільки в типі сортованих даних.    

    Створюючи узагальнену функцію, можна запрограмувати роботу алгоритму незалежно від типу оброблюваних даних. Після цього компілятор автоматично згенерує коректний програмний код для типу даних, який насправді встановлюється у процесі виконання цієї функції. Загалом, створюючи узагальнену функцію, створюється функція, яка автоматично перевизначає себе саму.

   Узагальнена функція створюється за допомогою ключового слова template. Звичайне значення слова "template" точно відображає мету його застосування у мові програмування C++. Це ключове слово використовують для створення шаблону (або оболонки), який описує дії, виконувані функцією. Компіляторові ж залишається "доповнити відсутні деталі" відповідно до заданого значення параметра.

    Загальний формат визначення шаблонної функції має такий вигляд:

template <class tType> тип ім'я_функції (перелік_параметрів)

{

// тіло функції

}

    У цьому записі елемент tType є "заповнювачем" для типу даних, які обробляються функцією. Це ім'я використовується в тілі самої функції. Але воно означає всього тільки заповнювач, замість якого компілятор автоматично підставить реальний тип даних при створенні конкретної версії функції. І хоча для задавання узагальненого типу в template-оголошенні за традицією застосовується ключове слово class, однак можна також використовувати ключове слово typename.

  1.   Шаблонна функція з одним узагальненим типом

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

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

                 типом

   // Визначення шаблонної функції.

template <class aType> void swapAB(aType &a, aType &b)

{    aType tmp;          // Створення тимчасової змінної

     tmp = a;

     a = b;

     b = tmp;

}

void 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(x, y); // Перестановка чисел з плинною крапкою

     swapAB(a, b); // Перестановка символів

     cout << "Після перестановки i, j: " << i << " " << j << endl;

     cout << "Після перестановки x, y: " << x << " " << y << endl;

     cout << "Після перестановки a, b: " << a << " " << b << endl;

}

   Внаслідок виконання ця програма відображає на екрані такі результати:

Початкові значення i, j: 10 20

Початкові значення x, у: 10.1 23.3

Початкові значення a, b: x z

Після перестановки i, j: 20 10

Після перестановки x, у: 23.3 10.1

Після перестановки a, b: z x

   Отже, розглянемо уважно код програми. Рядок template <class aType> void swapAB(aType &a, aType &b) повідомляє компілятор, по-перше, що створюється шаблон, і, по-друге, що тут починається узагальнене визначення шаблонної функції. Позначення aType є узагальненим типом, який використовується як "заповнювач". За template-заголовком знаходиться оголошення функції swapAB(), у якому символ aType означає тип даних для значень, які мінятимуться місцями. У функції main() продемонстровано виклик функції swapAB() з використанням трьох різних типів даних: int, double і char. Оскільки функція swapAB() є узагальненою, то компілятор автоматично створює три версії функції swapAB(): одну для обміну цілих чисел, другу для обміну чисел з плинною крапкою і третю для обміну символів.

   Тут необхідно уточнити деякі важливі терміни, пов'язані з шаблонами. По-перше, узагальнена функція (тобто функція, оголошення якої передує template-настанові) також називається шаблонною функцією. Обидва терміни використовуються як взаємозамінні. Коли компілятор створює конкретну версію цієї функції, то вважають, що створюється її спеціалізація (або конкретизація). Спеціалізація також називається породженою функцією (generated function). Дію породження функції визначають як її реалізацію (instantiating). Іншими словами, породжувана функція є конкретним примірником шаблонної функції.

    Оскільки мова програмування C++ не розпізнає символ кінця рядка як ознаку кінця настанови, то template-частина визначення узагальненої функції може не знаходитися в одному рядку з іменем цієї функції. У наведеному нижче прикладі показано ще один (достатньо поширений) спосіб форматування функції swapAB():

template <class aType>

void swapAB(aType &a, aType &b)

{     aType tmp;             // Створення тимчасової змінної

      tmp = a;

      a = b;

      b = tmp;

}

    При використанні цього формату важливо розуміти, що між template-настановою і початком визначення узагальненої функції ніякі інші настанови знаходитися не можуть. Наприклад, наведений нижче код програми не відкомпілюється:

// Цей програмний код не відкомпілюється

template <class aType>

int i;           // Тут помилка!

void swapAB(aType &a, aType &b)

{    aType tmp;     // Створення тимчасової змінної

     tmp = a;

     a = b;

     b = tmp;

}

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

  1.   Безпосередньо задане перевизначення узагальненої функції

    Незважаючи на те, що узагальнена функція сама перевизначається в міру потреби, однак це можна робити і безпосередньо. Формально цей процес називається безпосередньою спеціалізацією. При перевизначенні узагальнена функція перевизначається "на вигоду" цієї конкретної версії. Розглянемо, наприклад, наведену нижче програму, яка є переробленою версію першого прикладу.

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

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;

}

void 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;

}

    Внаслідок виконання ця програма відображає на екрані такі результати:

Початкові значення 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<>. Тип даних, для яких створюється ця спеціалізація, вказується в кутових дужках після імені функції. Для задавання будь-якого типу узагальненої функції використовується один і той самий синтаксис. На даний момент жоден з синтаксичних способів задавання спеціалізації не має жодних переваг перед іншим, але з погляду перспективи розвитку мови програмування, можливо, все ж таки краще використовувати новий стиль.

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

  1.   Шаблонна функція з двома узагальненими типами

    У template-настанові можна визначити декілька узагальнених типів даних, використовуючи перелік елементів, розділених між собою комами. Наприклад, у наведеному нижче коді програми створюється шаблонна функція з двома узагальненими типами.

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

                 типами

template <class aType, class bType> void FunC(aType a, bType b)

{    cout << a << " " << b << endl;

}

void main()

{    FunC(10, "Привіт");

     FunC(0.23, 10L);

}

 

   У наведеному прикладі у процесі виконання функції main(), коли компілятор генерує конкретні примірники функції FunC(), заповнювачі типів aType і bType замінюються спочатку парою типів даних int і char *, а потім парою double і long відповідно.


 

А также другие работы, которые могут Вас заинтересовать

42970. Расчет оборудования для вакуум-кристаллизации галургического хлорида калия на БКПРУ-4 1.03 MB
  Количество испаренной воды в каждой ступени рассчитываем по уравнению теплового баланса где Gnколичество щелока поступающего в nую ступень ВКУ кг ч; Сщел теплоемкость щелока кДж кгС; tн tк перепад температур в nой ступени ВКУ С; rn удельная теплота парообразования на nой ступени ВКУ кДж кг. Сводная таблица материального баланса Состав Приход кг ч Расход кг ч KCl раствор 8455216 3578556 KCl твердый 487666 NCl раствор 7241179 7241179 NCl твердый H2O раствор 27354605 24168545 H2O испаренная ...
42971. Принципиальная схема высокоэффективного импульсного регулятора напряжения постоянного тока 1.34 MB
  Регуляторыстабилизаторы напряжения или других параметров электроэнергии в цепях постоянного тока выполняются преимущественно на основе полупроводниковых приборов. На выходное напряжение преобразователя электроэнергии влияют различные факторы: изменение входного напряжения и тока нагрузки температура окружающей среды и др. Поскольку они вызывают изменения выходного напряжения их в этом смысле называют возмущающими. Точность поддержания напряжения при воздействии различных возмущающих факторов характеризуется соответствующими параметрами...
42972. Разработка ремонтной мастерской с ремонтно-технологической документацией на ремонт узлов металлоконструкции автомобильного крана 1.23 MB
  Определение годового объема работ по ТО и Р ремонтной мастерской и распределение трудоемкости по видам работ 15 1. Определение суммарного объема работ по ТО и Р 15 1. Годовой объем работ по отдельным зонам ремонтной мастерской 16 1. Распределение трудоемкости ТО по видам работ 17 1.
42973. Проектирование консольно-фрезерного станка 155.12 KB
  Серийным называется такое производство, при котором изготовление изделий производится партиями или сериями, состоящими из одноименных, однотипных по конструкции и одинаковых по размерам изделий.
42974. Разработка самозагружающегося скипового подъемника, предназначенного для загрузки составляющих в растворосмеситель 363.31 KB
  Дипломный проект состоит из расчетно-пояснительной записки содержащий 5 основных разделов и состоящий из 72 страниц машинописного текста и графической части состоящей из 9 листов чертежей. В расчётно-пояснительной записке дан обзор существующей российской техники для получения бетонной и растворной смесей и способов загрузки составляющих в смесители произведен расчёт на прочность скипового подъёмника а также расчет экономической эффективности рассмотрен вопрос безопасности жизнедеятельности приводится список используемой для выполнения...
42975. Цех ремонта сельхозтехники 103.5 KB
  площадь застройки промышленного здания в пределах внешнего периметра наружных стен. полезная площадь промышленного здания. Лёгкий бетон=1000 кг м3 Расчёт вспомогательных помещений Показатели для расчёта: Количество работающих во всех сменах: А=А1А2=8436=120 А1 мужчины А2 женщины Количество работающих в наиболее многочисленной смене: В=В1В2=4921=70 В1 мужчины В2 женщины Количество служащих: С=15 Вид помещений Показатель Значение Примечание Все вспомогательные помещения Площадь м2 504...
42976. Двухэтажный 4-квартирный жилой дом со стенами из керамических камней 87.5 KB
  Объемнопланировочное решение здания. Конструктивные решения здания. Характеристика района строительства Место расположения будущего здания в городе Рязань. Климатические условия района строительства: среднегодовая температура 38 0С минимальная зафиксированная температура 410С максимальная зафиксированная температура 380С продолжительность периода со среднесуточной температурой  0С составляет 145 суток количество осадков за год 644мм средняя месячная относительная влажность воздуха: наиболее холодного месяца...
42977. Цех по ремонту автотранспорта 61.5 KB
  Введение Исходные данные Характеристики климатического района Характеристика рельефа Характеристики огнестойкости и взрыво-пожаробезопасности Технологическая часть Направленность технологического процесса Технологические зоны Грузоподъемное оборудование Технологические зоны с агрессивными средами Объемно-планировочные решения Параметры проектируемого здания Помещения и перегородки Ворота Окна Полы Кровля Расчет количества водоприемных воронок Фасад...
42978. Газоснабжение жилого микрорайона в Советском районе г. Астрахань с газификацией жилого много квартирного дома 86 KB
  При определении сметной стоимости строительства внутренних инженерных систем использованы Территориальные единичные расценки на строительные работы ТЕР. ТЕР2001 предназначены для определения прямых затрат в сметной стоимости строительства а также для расчётов за выполненные строительные работы. Сборники ТЕР2001 разработаны в базисном уровне цен Госстроя по состоянию на 1 января 2001 года. При расчёте сметной стоимости базовоиндексным методом приняты: а Объёмы работ для подсчета сметной стоимости работ определяются в разделе...