В попередньому уроці ми розмовляли про функції і значення, які вона може повертати за допомогою оператора return. В цьому уроці ми дізнаємося, що таке параметри і аргументи функції.
Параметри і аргументи функції
У багатьох випадках нам потрібно буде передавати дані в функцію, що викликається, щоб вона могла з ними якось взаємодіяти. Наприклад, якщо ми хочемо написати функцію множення двох чисел, то нам потрібно якимось чином повідомити функцію, які це будуть числа. В іншому випадку, як вона дізнається, що на що множити? Тут нам на допомогу приходять параметри і аргументи.
Параметр функції — це змінна, яка використовується в функції і значення якої надає викликаюча функція. Параметри вказуються при оголошенні функції в круглих дужках. Якщо їх багато, то вони перераховуються через кому, наприклад:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Ця функція не має параметрів void doPrint() { std::cout << "In doPrint()" << std::endl; } // Ця функція має один параметр цілочисельного типу - a void printValue(int a) { std::cout << a << std::endl; } // Ця функція має два параметри цілочисельного типу - a і b int add(int a, int b) { return a + b; } |
Параметри кожної функції дійсні тільки всередині цієї функції. Тому, якщо і printValue() і add() мають параметр a
, то це не означає, що станеться конфлікт імен. Ці параметри вважаються окремими і ніяк не взаємодіють один з одним.
Аргумент функції — це значення, яке передається з викликаючої функції в функцію, що викликається і яке вказується в круглих дужках при виклику:
1 2 |
printValue(7); // 7 – це аргумент функції printValue() add(4, 5); // 4 і 5 – це аргументи функції add() |
Зверніть увагу, що аргументи також перераховуються через кому. Кількість аргументів має збігатися з кількістю параметрів, інакше компілятор видасть повідомлення про помилку.
Як працюють параметри і аргументи функцій?
При виклику функції, всі її параметри створюються як локальні змінні, а значення кожного з аргументів копіюється в відповідний параметр (локальну змінну). Цей процес називається “передача по значенню“, наприклад:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <iostream> // Ця функція має два параметри типу int: a і b // Значення змінних a і b визначає викликаюча функція void printValues(int a, int b) { std::cout << a << std::endl; std::cout << b << std::endl; } int main() { printValues(8, 9); // тут два аргумента: 8 і 9 return 0; } |
При виклику функції printValues() аргументи 8
і 9
копіюються в параметри a
і b
. Параметру a
присвоюється значення 8
, а параметру b
— значення 9
.
Результат:
Як працюють параметри і значення, що повертаються?
Використовуючи параметри і значення, що повертаються, ми можемо створювати функції, які можуть приймати і опрацьовувати дані, а потім повертати результат назад в викликаючу функцію.
Наприклад, ось проста функція, яка приймає два цілих числа і повертає їх суму:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <iostream> // Функція add() приймає два цілих числа в якості параметрів і повертає їх суму // Значення a і b визначає викликаюча функція int add(int a, int b) { return a + b; } // Функція main() не має параметрів int main() { std::cout << add(7, 8) << std::endl; // аргументи 7 і 8 передаються в функцію add() return 0; } |
При виклику функції add(), параметру a
присвоюється значення 7
, а параметру b
— значення 8
. Після цього функція add() обчислює їх суму і повертає результат назад в функцію main(), де він вже виводиться на екран.
Результат виконання програми вище:
Додаткові приклади
Розглянемо ще декілька викликів функцій:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include <iostream> int add(int a, int b) { return a + b; } int multiply(int c, int d) { return c * d; } int main() { std::cout << add(7, 8) << std::endl; // всередині функції add(): a = 7, b = 8, значить a + b = 15 std::cout << multiply(4, 5) << std::endl; // всередині функції multiply(): c = 4, d = 5, значить c * d = 20 // Ми можемо передавати цілі вирази в якості аргументів std::cout << add(2 + 3, 4 * 5) << std::endl; // всередині функції add(): a = 5, b = 20, значить a + b = 25 // Ми можемо передавати змінні в якості аргументів int x = 4; std::cout << add(x, x) << std::endl; // буде 4 + 4 std::cout << add(1, multiply(2, 3)) << std::endl; // буде 1 + (2 * 3) std::cout << add(1, add(2, 3)) << std::endl; // буде 1 + (2 + 3) return 0; } |
Результат виконання програми вище:
15
20
25
8
7
6
З першими двома викликами все зрозуміло.
В третьому виклиці, параметрами є вирази, які спочатку потрібно опрацювати. 2 + 3 = 5
і результат 5
присвоюється змінній a
. 4 * 5 = 20
і результат 20
присвоюється змінній b
. Результатом виконання функції add(5, 20)
є значення 25
.
Наступна пара досить легка:
1 2 |
int x = 4; std::cout << add(x, x) << std::endl; // буде 4 + 4 |
Тут уже a = x
і b = x
. Оскільки, x = 4
, то add(x, x) = add(4, 4)
. Результат — 8
.
Тепер розглянемо складніший виклик:
1 |
std::cout << add(1, multiply(2, 3)) << std::endl; // буде 1 + (2 * 3) |
При виконанні цього стейтменту процесор повинен визначити значення параметрів a
і b
функції add(). З параметром a
все зрозуміло — ми передаємо значення 1
(a = 1
). А ось, щоб визначити значення параметра b
, нам необхідно виконати операцію множення: multiply(2, 3)
, результат — 6
. Після цього add(1, 6)
повертає число 7
, яке і виводиться на екран.
Коротше кажучи:
add(1, multiply(2, 3)) => add(1, 6) => 7
Останній виклик може здатися трішки складним через те, що параметром функції add() є інший виклик add():
1 |
std::cout << add(1, add(2, 3)) << std::endl; // буде 1 + (2 + 3) |
Але тут все аналогічно прикладу вище. Перед тим як процесор визначить зовнішній виклик функції add(), він повинен опрацювати внутрішній виклик функції add(2, 3)
. add(2, 3) = 5
. Після цього процесор опрацьовує функцію add(1, 5)
, результатом якої є значення 6
. Потім 6
передається в std::cout на вивід.
Коротше кажучи:
add(1, add(2, 3)) => add(1, 5) => 6
Тест
Завдання №1: Що не так з наступним фрагментом коду?
1 2 3 4 5 6 7 8 9 10 |
void multiply(int a, int b) { return a * b; } int main() { std::cout << multiply(7, 8) << std::endl; return 0; } |
Завдання №2: Які тут є дві проблеми?
1 2 3 4 5 6 7 8 9 10 11 12 |
#include <iostream> int multiply(int a, int b) { int product = a * b; } int main() { std::cout << multiply(5) << std::endl; return 0; } |
Завдання №3: Який результат виконання наступної програми?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <iostream> int add(int a, int b, int c) { return a + b + c; } int multiply(int a, int b) { return a * b; } int main() { std::cout << multiply(add(3, 4, 5), 5) << std::endl; return 0; } |
Завдання №4: Напишіть функцію doubleNumber(), яка приймає ціле число в якості параметра, множить його на 2, а потім повертає результат назад в викликаючу функцію.
Завдання №5: Напишіть повноцінну програму, яка приймає ціле число від користувача (використовуйте std::cin), подвоює його за допомогою функції doubleNumber() з попереднього завдання, а потім виводить результат на екран.
Відповіді
Щоб переглянути відповідь, клікніть на неї мишкою.
Відповідь №1
Функція multiply() має тип повернення void, що означає, що ця функція не повертає значення. Але так як вона все рівно намагається повернути значення за допомогою оператора return, то ми отримаємо помилку від компілятора. Функція повинна мати тип повернення int.
Відповідь №2
Проблема №1: main() передає один аргумент в multiply(), але multiply() має два параметра.
Проблема №2: multiply() вираховує результат і присвоює його локальній змінній, яку не повертає назад в main(). А оскільки типом повернення функції multiply() є int, то ми отримаємо помилку (в деяких компіляторах) або неочікувані результати (в інших компіляторах).
Відповідь №3
Функція multiply() приймає наступні параметри: a = add(3, 4, 5)
і b = 5
. Спочатку процесор опрацьовує a = add(3, 4, 5)
, тобто 3 + 4 + 5 = 12
. Після цього вже виконує операцію множення, результатом якої стає число 60
.
Відповідь: 60.
Відповідь №4
1 2 3 4 |
int doubleNumber(int a) { return 2 * a; } |
Відповідь №5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <iostream> int doubleNumber(int a) { return 2 * a; } int main() { int a; std::cout<<"Enter a number: "; std::cin >> a; std::cout << doubleNumber(a) << std::endl; return 0; } /* // Наступне рішення є альтернативним int main() { int a; std::cout<<"Enter a number: "; std::cin >> a; a = doubleNumber(a); std::cout << a << std::endl; return 0; } */ |
Примітка: У вас можуть бути і інші рішення завдань №4 і №5 — це ок. В програмуванні є багато випадків, коли одну задачу можна вирішити декількома способами.