Функція — це іменована логічно завершена сукупність оголошень і операторів, призначених для виконання певної задачі [1, 4-8, 12-14,18, 20].
Програма мовою С++ містить одну або декілька функцій, кожна з яких повинна бути оголошена та визначена до її першого використання. Оголошення функції (прототип, заголовок) задає ім’я функції, тип значення, що повертає функція (якщо воно є), а також імена та типи аргументів, які можуть передаватися як у функцію, так і з неї. Визначення функції — це задання способу виконання операцій.
Слід нагадати, що серед функцій програми повинна бути одна з ім’ям main (головна функція), яка може знаходитися в будь-якому місці програми. Ця функція виконується завжди першою і закінчується останньою.
Усі функції мають однакову структуру визначення у вигляді:
[тип результату] ім'я функції ([список формальних аргументів]) { // тело функции опис даних; оператори; [return] [вираз]; };
де тип результату — будь-який базовий або раніше описаний тип значення (за винятком масиву і функції), що повертається функцією (необов’язковий параметр). За відсутності цього параметра тип результату за замовчуванням буде цілий (int). Він також може бути описаний ключовим словом (void), тоді функція не повертає ніякого значення. Якщо результат повертається функцією, то в тілі функції є необхідним оператор return вираз;, де вираз формує значення, що співпадає з типом результату;
ім’я функції — ідентифікатор функції, за яким завжди знаходиться пара круглих дужок «( )», де записуються формальні аргументи. Фактично ім’я функції — це особливий вид покажчика на функцію, його значенням є адреса початку входу у функцію;
список формальних аргументів — визначає кількість, тип і порядок проходження переданих у функцію вхідних аргументів, які розділяються комою («,»). У випадку, коли параметри відсутні, дужки залишаються порожніми або містять ключове слово (void). Формальні параметри функції локалізовані в ній і недоступні для будь-яких інших функцій.
Список формальних аргументів має такий вигляд:
([const] тип 1 [параметр 1], [const] тип 2 [параметр 2], . . .)
У списку формальних аргументів для кожного параметра треба вказати його тип (не можна групувати параметри одного типу, вказавши їх тип один раз).
Тіло функції може складатися з описів змінних і операторів. Змінні, що використовуються при виконанні функції, можуть бути глобальні і локальні. Змінні, що описані (визначені) за межами функції, називають глобальними. За допомогою глобальних параметрів можна передавати дані у функцію, не включаючи ці змінні до складу формальних параметрів. У тілі функції їх можна змінювати і потім отримані значення передавати в інші функції.
Змінні, що описані у тілі функції, називаються локальними або автоматичними. Вони існують тільки під час роботи функції, а після реалізації функції система видаляє локальні змінні і звільняє пам’ять. Тобто між викликами функції вміст локальних змінних знищується, тому ініціювання локальних змінних треба робити щоразу під час виклику функції. За необхідності збереження цих значень, їх треба описати як статичні за допомогою службового слова static, наприклад:
static int х, у; або static float р = 3.25;.
Статична змінна схожа на глобальну, але діє тільки у тій функції, в якій вона оголошена.
На початку програми можна не описувати всю функцію, а записати тільки прототип. Запис прототипу може містити тільки перелік типів формальних параметрів без імен, а наприкінці прототипу завжди ставиться символ “;», тоді як у описі (визначенні) функції цей символ після заголовка не присутній.
Механізм передачі параметрів є основним засобом обміну інформацією між функцією, що викликається, та функцією, яка викликає. Параметри, котрі зазначаються у заголовку опису функції, як відомо, називаються формальними, а параметри, які записані у операторах виклику функції — фактичними. Наведемо приклад фрагмента програми з використанням функцій:
double sqr (double ); //-------------- прототип функции sqr() main( ) //------------------ главная функция { //---------------- вызов функции sqr() cout << "Квадрат числа=" << sqr (10) << endl; } double sqr (double p) //---------------------- функция sqr() { return p*p; } //-------------- возврат no значению
У результаті виконання програми буде виведено:
Квадрат числа = 100
Функція завжди має бути визначена або оголошена до її виклику. При оголошенні, визначенні та виклику тієї самої функції типи та послідовність параметрів повинні співпадати. На імена параметрів обмежень на відповідність не існує, оскільки функцію можна викликати з різними аргументами, а в прототипах імена ігноруються компілятором (вони необхідні тільки для покращення читання програми). Тип значення, що повертає функція, та типи параметрів спільно визначають тип функції.
У найпростішому випадку при виклику функції слід вказати її ім’я, за яким у круглих дужках через кому – перелічити імена аргументів, що передаються. Виклик функції може здійснюватися у будь-якому місці програми, де за синтаксисом дозволяється вираз того типу, що формує функція. Якщо тип значення, що повертає функція не void, вона може входити до складу виразів або, у поодинокому випадку, розташовуватись у правій частині оператора присвоювання.
У мові С++ визначено декілька способів передачі параметрів і повернення результату обчислень функцій, серед них найбільш широке використання набули:
- виклик функції з передачею параметрів за допомогою формальних аргументів-значень;
- виклик функції з передачею адрес за допомогою параметрів-покажчиків;
- виклик функцій з використанням посилань, коли доступ до переданих параметрів забезпечується за допомогою альтернативного імені (синоніма);
- виклик функцій з передачею даних за допомогою глобальних змінних;
- виклик функцій з застосуванням параметрів, що задані за замовчуванням, при цьому можна використовувати або всі аргументи, або їх частину.
Виклик функції з передачею значень полягає у тому, що у функцію передаються не самі аргументи, а їх копії. Ці копії можна змінювати всередині функції, і це ніяк не позначиться на значеннях аргументів, що за межами функції залишаться без зміни, наприклад:
void fun (int р) //----------- функция fun() {++p; cout << " p = " << p << endl; } void main ( ) //----------- главная функция { int x = 10; fun (x); //----------- вызов функции cout << "x = " << x << endl; }
Результат роботи цього фрагмента програми:
р=11, х=10,
оскільки для виклику функції fun(x) до неї передається копія значення, що дорівнює 10. Всередині функції значення копії змінної збільшується на 1, тобто (++р), і тому виводиться
р = = 11, але за межами функції параметр р не змінюється. У цьому випадку функція не повертає ніякого значення.
При цьому способі для звертання до функції достатньо написати її ім’я, а в дужках — значення або перелік фактичних аргументів. Фактичні аргументи повинні бути записані в тій же послідовності, що і формальні, і мати відповідний тип (крім аргументів за замовчуванням і перевантажених функцій).
Якщо формальними аргументами функції є параметри-значення і в ній не використовуються глобальні змінні, функція може передати у викликаючу її програму лише одне значення, що записується в операторі return. Це значення передається в місце виклику функції. Достроковий вихід з функції можна також організувати з використанням оператора return.
Приклад 9.1. Скласти програму з використанням функції, що забезпечує підтримку російського шрифту.
// Р9_1.СРР — использование функции поддержки русского шрифта #include <iostream.h> #include <conio.h> const int n=100; //------------------------------- функция поддержки русского шрифта char *rus(char *text) { for (int і = 0; і < strlen(text); i++) if (text >= 'A' && text[i] <= 'n') text[i] = char(int(text[i]-64)); else if (text[i] >= 'р' && text[i] <= 'я') text[i] = char(int(text[i]-16)); return text; } //-------------------------------------------------------- главная функция void main() { char s[100]; cout << rus("введите строку на русском языке")<<endl; cin.getline(s,sizeof(s)); cout << s; getch(); }
Слід зауважити, що середовище С++ Builder та деякі інші середовища не підтримують російську символіку, і тому повідомлення російською мовою при потоковому виведенні «cout<<» представляються на екрані у вигляді псевдокодів. Так, підказка в операторі
cout <<“введите строку на русском языке”<<еndl;
при виконанні програми матиме такий вигляд:
ааШ6& Шіеб їй ббййШ
Застосування розробленої функції rus(char *text) дозволить на етапі виконання програми вивести російський текст без змін, тобто:
введите строку на русском языке .
За необхідності зміни параметра за межами тіла функції можна передати значення цього параметра за допомогою параметра-покажчика або за посиланням.
Виклик функції з використанням покажчиків забезпечує передачу до функції не значень параметрів, а їх адреси, тому можливо міняти значення цих змінних усередині функції і передавати за її межі (в інші функції).
У цьому випадку для виклику функції у списку формальних параметрів необхідно записати адресу того параметра, який слід змінити, тоді відповідний формальний параметр матиме тип покажчика на цей параметр. Усередині функції здійснюється розіменування параметра-покажчика та виконання необхідних дій. Програма з використанням виклику функції з передачею адрес за допомогою параметрів-покажчиків може мати вигляд:
// использование параметра-указателя
void fun 2 (int *p) { ++*p; cout << "*p = " << *p << endl; } void main ( ) { int x = 10; fun2 (&x); // вызов функции cout << "x = " << x << endl; }
У результаті буде виведена інформація:
*p = 11 і x = 11 .
Виклик функції з використанням параметра-посилання здійснює передачу до функції не самої змінної, а тільки посилання на неї. У цьому випадку забезпечується доступ до переданого параметра за допомогою визначення його альтернативного імені, бо, як відомо, посилання є синонімом імені параметра. Тоді всі дії, що відбуваються над посиланням, є діями над самою змінною. Такий спосіб передачі параметрів і повернення результату передбачає запис у списку фактичних параметрів імені змінної, а у списку формальних — параметрів-посилань.
Наприклад:
//-------------- использование параметра-ссылки void fun (int &p) //---------- функция fun() { ++p; cout << "p = " << p << endl; } void main ( ) { int x = 10; fun (x); //---------- вызов функции fun() cout << "x=" << x << endl; }
Одержимо результат попереднього фрагмента, тобто
р = 11 і х=11.
При застосуванні вказаних вище параметрів у функцію передаються не значення змінних, а їхні адреси, тому можливо міняти значення цих змінних усередині функції і передавати за її межі (в інші функції). Коли необхідно, щоб деякі параметри не змінювали свої значення всередині функції, їх слід оголосити як параметри-константи, використовуючи модифікатор const.
Використовувати глобальні змінні для передачі даних між функціями дуже легко, оскільки вони видимі в усіх функціях, де описані локальні змінні з тими ж іменами. Але такий спосіб не є поширеним, тому що ускладнює налагодження програми та перешкоджає розташуванню функції у бібліотеці загального використання. Слід прагнути, щоб функції були максимально незалежними, а їхній інтерфейс повністю визначався прототипом функції. Наведемо приклад використання глобальних змінних:
#include < iostream.h > int a, b, с; // глобальные параметры sum ( ); //----------- прототип функции main ( ) //----------- главная функция { cin >> а >>b; sum(); //----------- вызов sum() cout << с << endl; } sum( ) //----------- функция sum() { с = а + b; }
Приклади викликів функції з використанням покажчиків, посилань та глобальних змінних наведено в наступних підрозділах.
В останніх версіях мови С++ з’явилася можливість передавати дані за замовчуванням. У цьому випадку при написанні функції всім аргументам або декільком з них присвоюються початкові значення і задовольняються такі вимоги: коли якому-небудь аргументу присвоєно значення за замовчуванням, то всі аргументи, що розташовані за ним (тобто записані праворуч), повинні мати значення за замовчуванням. Таким чином, список параметрів поділяється на дві частини: параметри, що не мають значення за замовчуванням, і параметри, що мають такі значення.
У випадку виклику функції для параметрів, що не мають значень за замовчуванням, обов’язково повинен бути фактичний аргумент, а для параметрів, що мають значення за замовчуванням, фактичні аргументи можна опускати, коли ці значення не треба змінювати.
Якщо деякий параметр має значення за замовчуванням та для нього відсутній фактичний аргумент, то і для всіх наступних (тобто записаних пізніше) параметрів фактичні аргументи повинні бути відсутні, тобто їхні значення передаються до функції за замовчуванням, наприклад:
void functl (float х, int у, int z = 80) { cout << "x = " << x << " у = " << у << "z = " << z << endl; } void funct2 (float x, int у = 25, int z = 100) { cout << "x = " << x << "y = " << у << "z = " << z << endl; } void funct3 (float x = 3.5, int у = 40, int z = 200) { cout << "x = " << x << "y = " << у << "z = " << z << endl; } main ( ) { functl (5.1, 10); //пo умолчанию передаётся один аргумент — z funct2 (10.2); //пo умолчанию передаются два аргумента — у, z funct3 ( ); // по умолчанию передаются все аргументы }
На екрані буде виведено:
х = 5.1 у = 10 z = 80
х = 10.2 у = 25 z = 100
х = 3.5 у = 40 z = 200
З цієї ілюстраційної програми видно, що аргумент за замовчуванням — це той аргумент, значення якого задане при описі заголовка функції, а при її виклику його можна не вказувати.
Якщо замість параметра, заданого за замовчуванням при звертанні до функції, записується інше значення фактичного параметра, то значення за замовчуванням перекривається заданим фактичним значенням. Так, наприклад, в останньому програмному фрагменті при виклику функції functl (13.5, 75); на екрані буде виведено:
х = 13.5 у = 75 z = 80,
тобто z — прийнято за замовчуванням.
Приклад 9.2. Обчислити квадратну функцію вигляду у = ах2 + Ьх + с для заданого значення аргументу х з використанням функції, у яку коефіцієнти a, b і с можуть бути введені за замовчуванням.
// P9_2.CPP — вычисление квадратной функции y = axl +bx + c /* коэффициентыa, b и с вводятся в функцию по умолчанию */ #include <iostream.h> #include <conio.h> float ur (float х, float а = 0., float b = 0., float с = 0.); int main ( ) { float a =1., b = 2., с = 3., x = 0.5, y; cout << "\n***** Введены все аргументы " << endl; y = ur (x, а, b, с); //-------------- вызов функции ur() cout << " у = "<< у << endl; cout << "\n***** Введены аргументы x, a, b " << endl; у = ur (x, a, b); cout << " у = "<< у << endl; cout << "\y***** Введен аргумент x " << endl; у = ur (x); cout << " у = "<< у << endl; getch (); // задержка экрана } //--------------- функция вычисление квадратной зависимости float ur (float х, float a, float b, float с) { return a*x*x + b*x + c; }
Результати виконання програми:
***** Введены все аргументы
у = 4.25
***** Введен аргумент х
у = 0
***** Введены аргументы х, a, b
у = 1.25
якщо виникає необхідність збереження значень локальних змінних між викликами функції, то вони повинні бути оголошені як статичні, тобто з описом static, наприклад:
static char st[ ] = “Гакк М.Ю.”;.
Хороший сайт