Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
консплекС++1к 2013.doc
Скачиваний:
0
Добавлен:
31.12.2019
Размер:
667.14 Кб
Скачать

Лекція 8. Перевантаження функцій. Шаблони функцій.

План лекції (2 години)

  1. Мета перевантаження функції

  2. Мета перевантаження функції

  3. Забезпечення перевантаження функції.

  4. Шаблон функції

  5. Основні властивості параметрів шаблону

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

Забезпечення перевантаження функції.

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

int max_element(int n, int array[]) //Функція для масивів з елементами типу int

{int value=array[0]; for (int i=1;i<n;i++) value=value<array[i]?value:array[i];

pDC->TextOut(50,50,” Для (int) :”; return value;}

double max_element(int n, double array[]) //Функція для масива з елементами типу double

{double value=array[0]; for (int i=1; i<n; i++) value=value>array[i]?value:array[i];

pDC->TextOut(20,20,”Для (double) : “; return value; }

{ int x[]={10,20,30,40,50,60}; double z[]={0.01,0.02,0.03,0.04,0.05,0.06};

s.Format(”max_element(6,x)=%d”,max_element(6,x));pDC->TextOut(20,30,s);

s.Format(”max_element(6,z)=%g”,max_element(6,z));pDC->TextOut(20,60,s);

Результат роботи програми:

Для (int) :max_element(6,x)=60

Для (double) :max_element(6,z)=0.06

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

При використанні перевантажених функцій потрібно обережно задавати початкові значення їх параметрів. Визначимо перевантажену функцію множення різної кількості параметрів таким чином: double multy(double x) {return x*x*x;}

double multy(double x, double y) {return x*y*y;}

double multy(double x, double y, double x) {return x*y*x;}

Кожне з наступних звернень до функції multy() буде однозначно ідентифіковане і правильно оброблене: multy(0.4) multy(4.0,12.3) multy(0.1е-6, 1.2е4, 6.4)

Додавання до програми такої функції прототипу з початковими значеннями параметрів: double multy(double a=1.0, double b=1.0, double c=1.0, double d=1.0); return a*b+c*d);}призведе до некоректної дії при такому виклику: multy (0.1e-6, 1.2e4).

Шаблон функції

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

У визначенні шаблону сімейства функцій використовується службове слово template. Для параметризації використовується список формальних параметрів шаблону, який записаний у кутових дужках <>. Кожен формальний параметр шаблону позначується службовим словом class, слідом за яким записується ім’я параметра (ідентифікатор). Приклад визначення шаблону функцій, що обчислюють абсолютне значення числових величин різних типів: template <class type> type abs (type x) {return x >0?x:-x;}

Шаблон сімейства функцій складається з двох частин – заголовка шаблона:

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

template <class T> void swap (T*x, T* y) {T z=*x; *x=*y; *y=z;}

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

Шаблон сімейства функцій служить для автоматичного формування конкретних визначень функцій за тими викликами, які транслятор виявляє у тексті програми. Наприклад, якщо програміст звертається через abs(-10.3), тоді на основі наведеного вище шаблону компілятор створить таке визначення функції: double abs(double x) {return x>0?x:-x;}

Виконається потрібна функція, у точку виклику повернеться числове значення 10.3.

Якщо у програмі присутній наведений вище шаблон сімейства функцій swap() і виникне послідовність операторів int k=4, d=8; swap(&km&d);, тоді компілятор визначить функцію:void swap(int * x, int* y) {int z=*x; *x=* y; *y=z;}

Виконається звернення саме до цієї функції і значення змінних k, d поміняються місцями. Якщо у тій же програмі присутні оператори: double a=2.44, b=66.3; swap (&a,&b); , тоді виконається функція void swap (double* x, double* y) {double z=*x; *x=* y; *y=z;}

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

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

Основні властивості параметрів шаблону

Назвемо основні властивості параметрів шаблонів:

  1. Імена параметрів шаблону повинні бути унікальними у всьому визначенні шаблону.

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

  3. У списку параметрів шаблону функції може бути кілька параметрів. Кожен з них повинен починатися службовим словом class. Наприклад, допустимий такий заголовок шаблона: template <class type1, class type2>

Відповідно, не коректним буде заголовок: template <class type1,type2,type3>

  1. Недопустимо використовувати у заголовку шаблону параметри з однаковими іменами, тобто помилковим буде заголовок: template <class t, class t, class t>

  2. Ім’я параметра шаблону ( у наведених прикладах type1,type2, тощо) має у функції, що визначаєтьяс шаблоном, всі права імені типу, тобто через нього можна специфікувати формальні параметри, визначатися тип поверненого функцією значення та типи довільних об'єктів, локалізованих у тілі функції. Ім’я параметра шаблону видно у всьому визначенні та ховає інші використання того ж ідентифікатора в області, глобальній по відношенню до даного шаблону функцій. Якщо у тілі функції, що визначається, потрібен доступ до зовнішніх об’єктів з тим же іменем, тоді потрібно застосувати операцію зміни області видимості. Наступна програма ілюструє вказану особливість імені параметра шаблону функцій:

int N; // Ініційована по замовчуванні нулевим значенням

//Функція визначає максимальне з двох значень параметрів

template <class N>

N max(N x,N y) { N a=x; cout<< “\nЛічильник звернень N=”<<++::N;

if (a<y) a=y; return a; }

int a=12, b=42; max(a,b); double z=66.3, f=222.4; max(z,f);

Результат виконання програми:

Лічильник звернень N=1

Лічильник звернень N=2

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

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

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

template <список_параметрів_шаблону >

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