Мова С++ надає можливість використовувати однакові імена для декількох функцій. Звичайно різні функції мають різні імена, але інколи виникає потреба у тому, щоб одна функція виконувала схожі дії над об’єктами різних типів. У цьому випадку є сенс визначити декілька функцій з однаковим іменем, але різним тілом. Такі функції повинні мати набори аргументів, які відрізняються, для того щоб компілятор міг їх розпізнавати. В цьому випадку йде мова про перевантаження функцій. Головна перевага перевантажених функцій — це можливість визначання кількох функцій з однаковим іменем, але з різними типами або числом параметрів, при цьому тип результату, що повертається, може не змінюватись.
Приклад 9.10. Написати приклад програмної реалізації а використанням перевантаження функцій.
// Р9_10.СРР — использование перегрузки фунщий #include <iostream.h> #include <string.h> #include <conio.h> int funp(int x) //------- 1-я функция { return x*x; } int funp(unsigned x) //------- 2-я функция { return -x*x; } char funp(char x) //------- 3-я функция { return x+3; } int funp(int x, char *y) //------- 4-я функция { return x*strlen(y); } int funp(int x, char у) //------- 5-я функция { return x*y; } float funp(float r) //------- 6-я функция { return r*r; } float funp(double r) //------- 7-я функция { return r+r; } main ( ) { cout << funp(5) << endl; //результат 25 cout << funp((unsigned)10) << endl; //результат -100 cout << funp('a') << endl; //результат у cout << funp(4,"abc") << endl; //результат 12 cout << funp(4, 'a') << endl; //результат -128 cout << funp((float) 1.2) << endl; //результат 1.44 cout << funp((double) 4.5) << endl; //результат 9 getch(); return 0; }
Процес пошуку відповідної функції із багатьох перевантажених полягає в знаходженні найкращого співвідношення типів формальних та фактичних параметрів.
Приклад 9.11. З використанням перевантаження функцій написати програму обчислення площі квадрата, прямокутника та трикутника.
/* Р9_11.СРР — вычисления площадей квадрата, прямоугольника и треугольника с использованием перегрузки функций */ #inchide <iostream.h> #include <conio.h> int sfig(int a) // функция вычисления площади квадрата { return а*а; }int sfig (int a, int b) // функция вычисления площади прямоугольника { return a*b; }float sfig(int a, float h) //функция вычисления площади треугольника { return a*h/2;} void main() { int a, b; float h; //------------------- ввод стороны квадрата и вычисление площади cout << "Vvedite storonu kvadrata\n "; сіn >> a; cout << "s=" << sfig (a) << "\n"; //--------------- ввод сторон прямоугольника и вычисление площади cout << "Vvedite storony pijamougolnika\n "; сіn >> a >> b; cout <<"s=" << sfig (a,b) << "\n"; //---- ввод основания и высоты треугольника и вычисление площадиcout << "Vvedite storony і vysotu treugo!nika\n "; сіn >> a >> h; cout << "s=" << sfig (a,h) << "\n"; getch (); }
У наведеній програмі перша функція відрізняється від інших кількістю параметрів, а друга і третя функції — типом параметрів та типом результату.
Використовуючи перевантажені функції, треба бути уважними з числовимиаргументами-константами. Наприклад, якщо обчислюючи площу трикутника, визвати функцію таким чином:
cout<<“s=”<<sfig (4,3)<< “\n”;
то одержимо площу прямокутника, бо «3» — константа типу int, а потрібно float:
cout<<“s=”<<sfig (4,3.0)<< “\n”;
або
cout<<“s=”<<sfig (4,(float)3)<< “\n”;
У процесі розв’язання багатьох задач необхідно використовувати функції, в яких алгоритм обчислення однаковий, а типи даних відрізняються. Прикладом є задачі пошуку і сортування. Особливістю програмування таких задач мовою С++ є використання шаблонів функцій.
Шаблони функцій — потужний засіб параметризації. За допомогою шаблона функції можна визначити алгоритм, який буде застосовуватися до даних різних типів, а конкретний тип даних передається функції у вигляді параметра на етапі компіляції.
Шаблон функції — це деяка узагальнена функція (родова функція) для сімейства функцій, призначених для розв’язання даної задачі. Визначається така шаблонна функція у заголовочному файлі і має такий вигляд:
template <class Т>
type_func my_func (type paraml, type param2, …)
{
// операторы тела функции
}
де template <class T> — зарезервований вираз (заголовок шаблону), який вказує компілятору оголошений користувачем ідентифікатор типу Т;
type_func — тип шаблонної функції;
my_func — довільний ідентифікатор шаблонної функції;
type param1, type param2 — формальні параметри, з яких хоча б один повинен мати або наведений у заголовку (template cclass type>) тип Т, або покажчик *param на змінну типу Т (Т *param), або посилання ¶m на змінну типу Т (Т ¶m);
оператори тіла функції — схема реальних операторів, що генеруються компілятором у відповідну функцію, враховуючи тип даних, вказаних при виклику.
У шаблоні функції може бути оголошено декілька формальних типів даних, а також використано параметри означених раніше типів. Наприклад:
template <class ТІ, class T2>
typefunc my_func(Ti a,double x,T2 b,int c.char s)
{
//операторы тела функции
}
Таким чином, оголошення шаблонів функцій завжди починається з ключового словаtemplate (шаблон), за ним у кутових дужках визначається список формальних типів, перед кожним з яких вказується ключове слово class (поняття класу розглянуто у розділі 11.1).Далі йде звичайний опис функції. При цьому формальні типи, представлені у заголовку шаблону, можна використовувати в опису функції для задання типів аргументів функції, типу значення, що повертається, а також для оголошення змінних усередині тіла функції.
Приклад 9.12. Написати шаблон функції, що повертає мінімальний елемент масиву, застосувати цю функцію для обробки масивів різних типів.
/* Р912.СРР — использование шаблона функции для вычисления минимального элемента массивов разных типов */ #include <iostream.h> #include <conio.h>//--------------------------------------------- шаблон функции template <class T> T minmas (Т *а, int k) { Т min = a[0]; for (int і = 1; і < k; i++) if (a[i] < min) min = a[i]; return min; } //--------------------------------------------- главная функция void main() {int b[ ]={1, 6, 8, 5, 9, -6, 4, -5, 2;//целочисленный массив //---------------- вызов функции minmas() и вывод результатов cout <<" min массива в[ ]= "<<minmas(b, sizeof(b)/sizeof(int)); cout << endl; float c[ ]={-4.5, 6.4, 7.0, -6.3, 2.1}; //массив вещественных чисел cout <<" min массива c[ ]= "<<minmas(c, sizeof(c)/sizeof(float)); getch(); }
Результат обчислень:
min массива в[ ]=-6
min массива с[ ]=-6.3
У заголовку шаблону цієї функції оголошено єдиний формальний параметр Т як тип даних, що повинні оброблятися функцією minmas(). У заголовку функції параметр Т використовується для задания типу значення функції, що повертається (Т minmas), та для задання типу показчика *а. Усередині функції параметр Т застосовано для визначення типу локальної змінної тіл. Завдяки цьому шаблону у програмі можна обробляти масиви різних типів.