Параметры и аргументы функций. Урок 13

На предыдущем уроке мы говорили о том, что функция может возвращать значение обратно в caller, используя оператор return. На этом уроке мы узнаем, что такое аргументы в функции и что такое параметры в функции.

Параметры и аргументы функций

Во многих случаях нам нужно будет передавать данные в вызываемую функцию, чтобы она могла с ними как-то взаимодействовать. Например, если мы хотим написать функцию умножения двух чисел, то нам нужно каким-то образом сообщить функции, какие это будут числа. В противном случае, как она узнает, что на что перемножать? Здесь нам на помощь приходят параметры и аргументы.

Параметр функции — это переменная, которая используется в функции, и значение которой предоставляет caller (вызывающий объект). Параметры указываются при объявлении функции в круглых скобках. Если их много, то они перечисляются через запятую, например:

// Эта функция не имеет параметров
void doPrint()
{
   std::cout << "In doPrint()" << std::endl;
}
 
// Эта функция имеет один параметр типа int: a
void printValue(int a)
{
   std::cout << a << std::endl;
}
 
// Эта функция имеет два параметра типа int: a и b
int add(int a, int b)
{
   return a + b;
}

Параметры каждой функции действительны только внутри этой функции. Поэтому, если printValue() и add() имеют параметр с именем a, то это не означает, что произойдет конфликт имен. Эти параметры считаются независимыми и никак не взаимодействуют друг с другом.

Аргумент функции — это значение, которое передается из caller-а в функцию и которое указывается в скобках при вызове функции в caller-е:

printValue(7); // 7 – это аргумент функции printValue()
add(4, 5); // 4 и 5 – это аргументы функции add()

Обратите внимание, аргументы тоже перечисляются через запятую. Количество аргументов должно совпадать с количеством параметров, иначе компилятор выдаст сообщение об ошибке.

Как работают параметры и аргументы функций?

При вызове функции, все её параметры создаются как локальные переменные, а значение каждого из аргументов копируется в соответствующий параметр (локальную переменную). Этот процесс называется передачей по значению. Например:

#include <iostream>
 
// Эта функция имеет два параметра типа int: a и b
// Значения переменных a и b определяет caller
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.

Результат:

8
9

Как работают параметры и возвращаемые значения функций?

Используя параметры и возвращаемые значения, мы можем создавать функции, которые будут принимать и обрабатывать данные, а затем возвращать результат обратно в caller.

Например, простая функция, которая принимает два целых числа и возвращает их сумму:

#include <iostream>
 
// Функция add() принимает два целых числа в качестве параметров и возвращает их сумму
// Значения a и b определяет caller
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(). И тогда уже результат выводится на экран.

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

15

Еще примеры

Рассмотрим еще несколько вызовов функций:

#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 присваивается переменной a4 * 5 = 20 и результат 20 присваивается переменной b. Результатом выполнения функции add(5, 20) является значение 25.

Следующая пара относительно лёгкая для понимания:

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.

Теперь рассмотрим вызов посложнее:

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():

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: Что не так со следующим фрагментом кода?

#include <iostream>
 
void multiply(int a, int b)
{
   return a * b;
}
 
int main()
{
   std::cout << multiply(7, 8) << std::endl;
   return 0;
}

Задание №2: Какие здесь есть две проблемы?

#include <iostream>
 
int multiply(int a, int b)
{
   int product = a * b;
}
 
int main()
{
   std::cout << multiply(5) << std::endl;
   return 0;
}

Задание №3: Какой результат выполнения следующей программы?

#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(), которая принимает целое число в качестве параметра, удваивает его, а затем возвращает результат обратно в caller.

Задание №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
int doubleNumber(int a)
{
   return 2 * a;
}
Ответ 5
#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;
}
*/
Прогаем.ру
Добавить комментарий