68956

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

Лекция

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

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

Украинкский

2014-09-28

54.5 KB

0 чел.

Лекція № 18

Тема: Шаблони

План

  1.  Узагальнені функції
  2.  Функція з двома узагальненими параметрами
  3.  Явне перевантаження узагальненої функції

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

Узагальнені функції

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

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

template <class Tтип> тип_возвращаемого_значения

имя_функции (список_параметров)

{

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

}

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

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

// Приклад шаблонної функції.

#include <iostream>

using namespace std;

// шаблон функції

Template <class X> void swapargs(X &a, X &b)

{

X temp;

temp=a; a=b; b=temp;

}

int main()

{

int i=10, j=20;

double x=10.1, y=23.3;

char a=’x’, b=’z’;

cout << “Вихідні значення i, j: ” << i << ‘ ’ << j << ‘\n’;

cout << “Вихідні значення x, y: ” << x << ‘ ’ << y << ‘\n’;

cout << “Вихідні значення a, b: ” << a << ‘ ’ << b << ‘\n’;

swapargs(i, j);

swapargs(x,y);

swapargs(a,b);

cout << “Змінені значення i, j: ” << i << ‘ ’ << j << ‘\n’;

cout << “Змінені значення x, y: ” << x << ‘ ’ << y << ‘\n’;

cout << “Змінені значення a, b: ” << a << ‘ ’ << b << ‘\n’;

return 0;

}

Розглянемо цю програму докладніше. Рядок

template <class X> void swapargs(X &а, X &b)

повідомляє компілятор, що: по-перше, створюється шаблон, і, по-друге, починається опис узагальненої функції. Тут параметр X задає узагальнений тип, який згодом буде замінений фактичним типом. Після цього рядка оголошується функція swapargs(), у якій змінні, що підлягають перестановці, мають узагальнений тип X. У функції main() функція swapargs Про викликається для трьох різних типів даних: int, double і char. Оскільки функція swapargs () є узагальненою, компілятор автоматично створює три її версії: для перестановки цілих і дійсних чисел, а також символів.

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

Оскільки мову C++ не рахує кінець рядка символом кінця оператора, розділ template у визначенні узагальненої функції не зобов'язаний знаходитися в одному рядку з ім'ям функції. Цю особливість ілюструє наступний приклад.

 

template <class X>

void swapargs(X &a, X &b)

{

X temp;

temp = а ; а = b; b = temp;

}

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

 

// Цей фрагмент містить помилку.

template <class X>

int i; // Помилка

void swapargs(X &a, X &b)

{

X temp;

temp = а; а = b; b = temp;

}

 

Як випливає з коментаря, специфікація template повинна безпосередньо передувати визначенню функції.

Функція з двома узагальненими типами

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

#include <iostream>

using namespace std;

template <class typel, class type2>

void myfunc(typel x, type2 у)

{

cout « x « ' ' « у << ' \n';

}

int main()

{

myfunc(10, "Я люблю C++");

myfunc(98.6, 19L);

return 0;

}

При генерації конкретних екземплярів функції myfunc() компілятор замінює шаблонні типи typel і type2 типами int і char*, а також double і lone відповідно.

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

Явне перевантаження узагальненої функції

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

 

// Заміщення шаблонної функції.

#include <iostream>

using namespace std;

template <class X> void swapargs(X &a, X &b)

{

X temp;

temp = а; а = b; b = temp;

cout « "Усередині функції swapargs.\n";

}

// Ця функція заміщає узагальнену версію функції

// swapargs(), призначену для перестановки цілих чисел.

void swapargs(int &a, int &b)

{

int temp;

temp = а; а = b;

b = temp;

cout « "Усередині спеціалізації функції swapargs для цілих чисел.\n";

}

 

int main() {

int i=10, j=20;

double x=10.1, y=23.3;

char a='x', b= ' z ' ;

cout << “Вихідні значення i, j: ” << i << ‘ ’ << j << ‘\n’;

cout << “Вихідні значення x, y: ” << x << ‘ ’ << y << ‘\n’;

cout << “Вихідні значення a, b: ” << a << ‘ ’ << b << ‘\n’;

swapargs(i, j); // Виклик явно переобтяженої функції swapargs().

swapargs(х, у); // Виклик узагальненої функції swapargs().

swapargs(а, b); // Виклик узагальненої функції swapargs()

 

cout << “Переставлені значення i, j: ” << i << ‘ ’ << j << ‘\n’;

cout << “Переставлені значення x, y: ” << x << ‘ ’ << y << ‘\n’;

cout << “Переставлені значення a, b: ” << a << ‘ ’ << b << ‘\n’;

return 0;

}

 

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

Недавно з'явилася нова синтаксична конструкція, призначена для позначення явної спеціалізації функції. Цей метод використовує ключове слово template. Наприклад, переобтяжену функцію swapargs() з попереднього прикладу можна переписати таким чином.

// Нова синтаксична конструкція для спеціалізації

template<> void swapargs<int>(int &a, int &b)

{

int temp;

temp = а;

а = b;

b = temp;

cout << "Усередині спеціалізації  swapargs для цілих чисел.\n";

}

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

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


 

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

45494. Методы построения датчиков случайных чисел 75.5 KB
  Генератор случайных чисел ГСЧ Основа метода МонтеКарло ГСЧ равномерно распределенных в интервале 01. Такая последовательность чисел должна обладать математическим ожиданием и дисперсией Если окажется что случайные числа должны быть распределены в другом интервале то преобразование имеет вид: ГСЧ ррb x:= b r Пример: x:= 313r r:=0 x:=3r:=1 x:=10r:=0. ГСЧ порождает случайный поток событий с равномерным законом распределения. ГСЧ делятся на: физические; табличные; алгоритмические.
45495. Общие принципы построения моделирующих алгоритмов 47.5 KB
  Общие принципы построения моделирующих алгоритмов Проблема при составлении алгоритмов на последовательной машине состоит в том что при моделировании необходимо отслеживать множество параллельных процессов во времени. Основные методы Принцип Принцип особых состояний Принцип последовательной проводки заявок Принцип параллельной работы объектов Принцип Определение состояния системы в фиксированные моменты времени: t t t2 Особенности: самый универсальный и простой метод описывает широкий класс объектов Недостатки: самый...
45496. Иерархия протоколов 304 KB
  Информационная совместимость – это правила передачи информации от одного узла к другому. Для того чтобы передать информацию от одного узла другому используют как минимум три уровня: физический; канальный; сетевой; На физическом уровне описаны характеристики передающей среды Основной задачей канального уровня является преобразование физической среды в канал передачи данных а так же выявление ошибок и деление информации на кадры. Кадр – единица измерения для передачи информации для сетей. Первые четыре уровня обеспечивают...
45497. Теоретические основы передачи данных 378.5 KB
  Ограничения на пропускную способность передачи данных.5c ∑ n sin2pnft∑ bncos2pnft f – частота nbn – амплитуды nой гармоники t – время передачи сигнала gt – определенное ограничение на пропускную способность. При этом скорость передачи информации зависит от способа кодирования и скорости изменения кодирования.
45498. Магистрали 261 KB
  Основное достижение – это применение одного канала для передачи сигналов между различными источниками и приемниками. Основано на разделении передачи сигналов от разных источников по различным несущим частотам. Это связано с тем что пропускная способность составляет 25000 Гц и за счет этого в оптических каналах скорость передачи на порядок выше. Это связано с тем что после получения канала с аналоговой петли скорость передачи данных может быть увеличена в несколько раз поэтому для цифровых каналов связи применяется метод мультиплексирования...
45499. Коммутация 466 KB
  Для систем передачи используются три способа коммутации: коммутация сообщений; коммутация каналов; коммутация пакетов. При использовании коммутации каналов снижаются накладные расходы на передачу информации. При коммутации пакетов все сообщения разделяются на определенные пакеты. В отличие от коммутации каналов абонент не может монополизировать линию.
45500. Использование амплитудно-импульсной модуляции (АИМ) для построения систем передачи с временным разделением канала 311.5 KB
  При амплитудноимпульсной модуляции амплитуда периодической последовательности импульсов изменяется в соответствии с изменеием модулирующего сигнала. АИМ1 – амплитуда импульсов пропорциональна амплитуде моделирующего сигнала. При преобразовании: частота дискретизации; скважность – определяет количество времени свободное для передачи сигнала. Для простоты моделирующее колебание представляется: Для амплитудномоделирующей последовательности выражение: показывает глубину модуляции после преобразования получим ряд: Из данного...
45501. Использование широкоимпульсной модуляции (ШИМ) для построения систем передачи с временным разделением канала 299 KB
  Использование фазовоимпульсной модуляции ФИМ для построения систем передачи с временным разделением каналов. ФИМ является более помехоустойчивым видом модуляции чем ШИМ и АИМ. При ФИМ используется следующий моделирующий сигнал: В этом случае основным определяющим элементом является величина фазового сдвига которая определяется по следующей формуле: ∆τmx – максимальный временной сдвиг между импульсами: ∆τmx=MФИМUmx MФИМ – коэффициент глубины модуляции. Модуляция фазы импульсов определяется в соответствии со следующим...
45502. CASE-средства. Общая характеристика и классификация 51 KB
  Общая характеристика и классификация Современные CSEсредства охватывают обширную область поддержки многочисленных технологий проектирования ИС: от простых средств анализа и документирования до полномасштабных средств автоматизации покрывающих весь жизненный цикл ПО. Наиболее трудоемкими этапами разработки ИС являются этапы анализа и проектирования в процессе которых CSEсредства обеспечивают качество принимаемых технических решений и подготовку проектной документации. Графические средства моделирования предметной области позволяют...