Функция – это именованная область кода, которая может быть вызвана из других частей программы. Функции также часто называются подпрограммами. В любой программе на C++ обязательно должна быть как минимум одна функция – с именем main. Во всех примерах программ, приведённых ранее, это была единственная функция в программе. С нее начинается выполнение программы, но в реальных приложениях кроме нее создаются и другие функции, которые вызываются из main и друг из друга.
С использованием функции связаны 3 понятия – объявление функции (прототип), определение функции (реализация), и вызов функции. Определение функции состоит из её заголовка и тела:
тип_результата имя_функции (список_параметров) {
тело_функции;
}
Первая строка называется заголовком функции. В ней описывается:
- Тип результата – тип данных значения, которое возвращает функция в результате своей работы. В C++, в отличие от некоторых языков программирования, нет понятия процедуры – подпрограммы, не возвращающей значения. Поэтому если функция не должна возвращать значения, в качестве типа результата указывается void.
- Имя – название функции, т.е. любой допустимый в C++ идентификатор. Имя затем будет использовано для вызова функции.
- Список параметров содержит перечисление аргументов, разделённых запятыми. Эти параметры называются формальными. Каждый аргумент напоминает объявление переменной, т.е. состоит из имени типа и названия аргумента. Внутри функции параметры можно использовать как обычные переменные. Значения параметров передаются в функцию при вызове. Если функция не должна иметь параметров, то круглые скобки оставляют пустыми или указывают в них ключевое слово void.
После заголовка функции в фигурных скобках следует тело функции – последовательность инструкций, которые будут выполняться при вызове функции.
Если функция имеет тип результата, отличный от void, то она обязательно должна вернуть какое-либо значение. Это осуществляется с помощью оператора return выражение;. Данный оператор сразу же прерывает выполнение функции и возвращает указанное значение.
Если функция не возвращает значения, то выход из нее происходит после выполнения последней инструкции в теле, а оператор return необязателен. Если же он используется, то возвращаемое значение после него не указывается, т.е. он записывается в виде return;
Тело функции не может содержать определения других функций, т.е. функции в C++ не могут быть вложенными.
Примеры определения функции:
// определение максимума двух чисел
int max(int a, int b) {
return (a > b) ? a : b;
}
// определение среднего арифметического трех чисел
float avg(int num1, int num2, int num3)
{
return (num1 + num2 + num3) / 3.0;
}
// вывод на экран двумерного динамического массива
void print(double** arr, int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
cout.precision(3);
cout.width(6);
cout << arr[i][j] << ' ';
}
cout << '\n';
}
}
// вывод на экран текущего времени
void print_time() {
char time[9];
_strtime(time);
cout << time << '\n';
}
Вызов функции из программы выглядит следующим образом:
имя_функции(список_фактических_параметров)
Список фактических параметров должен соответствовать списку формальных параметров, заданных при определении функции. Приведённый ниже код демонстрирует использование вышеописанных функций.
// вызов max
int a = 5;
cout << max(a, 10) << '\n';
// вызов avg
float b = avg(50, a, max(0,5));
cout << b;
// вызов print
double **m = new double*[a];
for (int i = 0; i < a; i++)
m[i] = new double[3];
// ... заполнение массива m
print(m, a, 3);
// вызов print_time
print_time();
В примере в качестве одного из параметров функции avg указывается вызов функции max. В этом случае программа сначала вызовет max, после чего вызовет avg, использовав в качестве третьего аргумента значение, которое вернёт max.
Если функция не имеет аргументов, как print_time, то при её вызове указываются пустые круглые скобки.
Объявление функции (прототип) состоит только из заголовка функции. Причем в прототипе в списке параметров компилятор учитывает только типы данных аргументов. Имена аргументов игнорируются и указывать их не обязательно, хотя обычно это и делается. Прототипы используются для того, чтобы объявить функцию до её первого использования. Прототип описывает тип результата функции, а также количество и типы её аргументов. Компилятору необходимо знать эту информацию до первого вызова функции, поэтому объявления функций обычно помещают в самое начало программы, после директив #include и перед определением любых функций.
Примеры прототипов для описанных функций:
// чаще всего прототип полностью совпадает с заголовком определения
int max(int a, int b);
// имена параметров можно не указывать
float avg(int, int, int);
// можно указать другие имена – но зачем запутывать ситуацию?
void print(double** matrix, int n, int m);
void print_time();
Использование прототипов не обязательно. Обычно они применяются в больших программах, которые разбиты на множество модулей. Объявления функций помещаются в заголовочные файлы (с расширением .h), которые могут быть подключены в любом модуле. После этого функции, реализованные в одном модуле, будут доступны во всех остальных файлах программы.
Стандартные заголовочные файлы (iostream, math.h, string.h, stdio.h и т.д.) содержат именно прототипы функций. Их реализации содержаться в системных библиотеках, поставляемых вместе со средой разработки.
Объявления функций обязательны, если функция не может быть определена до её первого вызова. Например, в следующем случае:
void f2(); // без объявления будет ошибка: идентификатор f2 не найден