6 Перевантаження функцій
Часто буває зручно, щоб функції, які реалізовують однаковий алгоритм для різних типів даних, мали однакове ім’я. Якщо це ім ’я несе певну інформацію, це робить програму більш зрозумілою, оскільки для кожної дії треба пам’ятати лише одне ім’я. Використовування кількох функцій з однаковим ім’ям, але з різними типами параметрів називається перевантаженням функцій.
Компілятор визначає, яку саме функцію слід викликати, за типом фактичних параметрів. Цей процес називається дозволом перевантаження (переклад з англійського слова “resolution”). Тип значення , яке повертає функція, у дозволі не бере участі. Механізм дозволу ґрунтується на доволі складному наборі правил, зміст яких зводиться до того, щоб використати функцію з найбільш придатними аргументами й видати повідомлення, якщо така не віднайдеться. Мета перевантаження – зробити так, щоб функції з однаковим ім’ям виконувалися порізному (і за можливість повертали різні значення) при звертанні до них з різними за типами й кількістю параметрами. За приклад наведемо чотири варіанти функції для визначення максимального значення:
int max(int, int); // Повертає найбільше з двох цілих
char* max(char*, char*);//Повертає рядок максимальної довжини
Повертає найбільше значення з першого параметра і довжини рядка, переданого до функції в якості другого параметра
int max(int, char*);
Повертає найбільше значення з першого параметра і довжини рядка, переданого до функції в якості першого параметра
int max(char*, int);
void f(int a, int b, char* c, char* d)
{ cout << max(a,b) << max(c,d) << max(a,c) << max(c,b); }
Усі чотири функції мають однакове ім’я (max) й відрізняються типами па-раметрів (тому вважаються за різні функції). За викликання функції max() ком-пілятор обирає відповідно до типу фактичних параметрів варіант функції (у наведеному прикладі буде послідовно викликано всі чотири варіанти функції). Якщо точної відповідності не віднайдено, виконуються перетворювання порядкових типів відповідно до загальних правил, наприклад bool й char до int, float до double тощо. Далі виконуються стандартні перетворювання ти-пів, наприклад int до double, покажчиків до void* тощо. Наступним кроком є виконання перетворювань типів, заданих користувачем, а також пошук відпові-дностей за рахунок змінної кількості аргументів функції. Якщо відповідність на тому самому етапі може бути набута у понад один спосіб, виклик вважається за неоднозначний і видається повідомлення про помилку.
Неоднозначність може виникнути за:
перетворення типу;
використання параметрів-посилань;
використання аргументів за замовчуванням. Приклад неоднозначності за перетворення типу:
#include <iostream.h> int f(int a){return a;}
int f(int a, int b=1){return a*b;}
void main ()
{ cout << f(10,2); // Викликається f(int, int)
cout << f(10); } // Неоднозначність – що викликати: f(int, int) чи f(int)?
Слід відрізняти перевантаження функцій і редекларацію . Якщо функції з однаковим ім’ям мають однакові параметри і типи результату, вважається, що друге визначення розглядатиметься як редекларація (повторне визначення). Якщо параметри функцій з однаковим ім’ям збігаються і функцій відрізняються лише типом значення, яке повертається, це призведе до помилки.
Правила опису перевантажених функцій:
перевантажені функції мають перебувати в одній області видимості,інакше станеться приховування аналогічне до однакових імен змінних у вкладених блоках;
перевантажені функції можуть мати параметри за замовчуванням,прицьому значення одного й того самого параметра у різних функціях мають збігатися. У різних варіантах перевантажених функцій може бути різна кількість параметрів за замовчуванням.
Функції не можуть бути перевантажені, якщо опис їхніх параметрів відрізняється лише специфікатором const чи використанням посилання, наприклад int та const int чи int та int&.
Приклад 8.21 Написати три функції для обчислення периметра трикутника, чотирикутника й п’ятикутника відповідно.
Розв’язок. Завдання відрізняється від попереднього тим, що тип параметрів є однаковий, а кількість параметрів – різна. При викликанні функції обиратиметься той варіант, для якого збігається кількість фактичних і формальних параметрів.
Тексти функції та її виклику в основній програмі:
Визначення всіх потрібних версій функції
Версія функції для трикутника
int Perimetr(int Len1, int Len2, int Len3)
{ return Len1 + Len2 + Len3; } // Версія функції для чотирикутника
int Perimetr(int Len1, int Len2, int Len3, int Len4) { return Len1 + Len2 + Len3 + Len4; }
// Версія функції для п’ятикутника
int Perimetr(int Len1, int Len2, int Len3, int Len4, int Len5)
{ return Len1 + Len2 + Len3 + Len4 + Len5; } int main()
{ int AB = 5, BC = 3, CA = 7;
int CD = 8, DA = 11, DE = 2, EA = 9;
cout << "Perimetr ABC = " << Perimetr(AB, BC, CA) << "\n";
cout << "Perimetr ABCD = " << Perimetr(AB,BC,CD,DA) << "\n";
cout << "Perimetr ABCDE = " << Perimetr(AB, BC, CD, DE, EA);
getch();
}
Результати виконання програми:
Perimetr ABC = 15
Perimetr ABCD = 27
Perimetr ABCDE = 27
КОНТРОЛЬНІ ЗАПИТАННЯ
Для чого потрібні функції в програмах?
Для чого слугує прототип функції, яку він несе інформацію для транслятора?
Що таке аргументи функції?
Як розуміти фразу, яка закріпилася в програмістській термінології, що функція повертає значення?
Що таке тіло функції, що в ньому міститься?
Запишіть прототипи будь-яких функцій, що мають один аргумент цілого типу, два аргументи дійсного типу, два аргументи, один з яких цілого типу, а другий дійсного.
Для чого призначений оператор return?
Спробуйте оголосити, реалізувати функцію, яка приймає два аргументи цілого типу та повертає ціле число: найбільше значення з двох аргументів. Напишіть програму, в якій ця функція викликається.
Напишіть функцію, яка має один аргумент п цілого типу, запитує користувача та вводить з клавіатури п дійсних чисел та повертає їх суму. Скласти функцію main, з якої ця функція викликається.
Що таке тип void, як він використовується, чим відрізняється від усіх інших типів?
Поміркуйте, чи можна оголошувати в програмі змінні типу void. Відповідь обгрунтувати.
Написати функцію, яка приймає три аргументи, сторони трикутника, та повертає його площу. Передбачити випадок, коли трикутник з тикими сторонами не існує, в цьому випадку повернути спеціальне значення.
