Указатель на функцию фактически представляет некоторый тип, и функция также может иметь параметр, который представляет тип указателя на функцию. Таким образом, мы можем через параметр на функцию передавать в одну функцию другую. То есть функция может быть аргументом другой функции.
Рассмотрим пример:
#include <iostream> int add(int, int); int subtract(int, int); int operation(int(*)(int, int), int, int); // первый параметр - указатель на функцию int main() { int a{10}; int b{6}; int result = operation(add, a, b); std::cout << "result: " << result << std::endl; result = operation(subtract, a, b); std::cout << "result: " << result << std::endl; } int add(int x, int y) { return x + y; } int subtract(int x, int y) { return x - y; } int operation(int(*op)(int, int), int a, int b) { return op(a, b); }
В данном случае первый параметр функции operation - int (*op)(int, int)
- представляет указатель на функцию, которая возвращает
значение типа int и принимает два параметра типа int. Результатом функции является вызов той функции, на которую указывает указатель.
Определению указателя соответствуют две функции: add и subtract, поэтому их адрес можно передать в вызов функции operation: operation(add, a, b);
.
Результат работы программы:
result: 16 result: 4
Функция, передаваемая другой функции в качестве аргумента, называется функцией обратного вызова или коллбек (callback). А функция, которая принимает другую функцию в качестве аргумента, является функцией высшего порядка. Таким образом, в примере выше функция operation представляет функцию высокого порядка, а функции add и subtract - функции обратного вызова.
Рассмотрим другой пример - определим функцию, которая может принимать в качестве параметра некоторое условие и вычислять все элементы массива, которые соответствуют этому условию:
#include <iostream> // функции, которые представляют условия bool isEven(int); // если число четное bool isPositive(int); // если число положительное // Функция для определения элементов массива, которые соответствуют некоторому условию // функция принимает условие - bool(*)(int) // массив - int[] // размер массива - unsigned void action(bool(*)(int), int[], unsigned); int main() { int numbers[]{ -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 }; const unsigned n { std::size(numbers)}; // находим длину массива std::cout << "Even numbers: " << std::endl; action(isEven, numbers, n); // находим числа, которые соответствуют условию isEven std::cout << "\nPositive numbers: " << std::endl; action(isPositive, numbers, n); // находим числа, которые соответствуют условию isPositive } bool isEven(int x) { return x % 2 == 0; } bool isPositive(int x) { return x > 0; } void action(bool(*condition)(int), int numbers[], unsigned n) { // перебираем массив for (unsigned i{}; i < n; i++) { // если число (numbers[i] соответствует условию condition if (condition(numbers[i])) { std::cout << numbers[i] << "\t"; } } std::cout << std::endl; }
Функция action в качестве первого параметра принимает некоторую функцию, которая задает условие, которому должны соответствовать элементы массива. Это условие
представляет указатель bool (*condition)(int)
. То есть это некоторая функцию, которая принимает целое число и в зависимости от того, соответствует оно условию или
нет, возвращает значение типа bool
(true
, если число из массива соответствует условию, и false
, если не соответствует).
На момент определения функции action точное условие может быть неизвестно.
В текущей программе условия представлены двумя функциями. Функция isEven()
возвращает true, если число четное, и false, если число нечетное.
А функция isPositive()
возвращает true, если число положительное, и false, если отрицательное.
Второй параметр функции action - массив чисел int, для которых вызываем условие. А третий параметр - размер массива. Если число соотвествует условию, то выводим это число на консоль
void action(bool(*condition)(int), int numbers[], unsigned n) { // перебираем массив for (unsigned i{}; i < n; i++) { // если число (numbers[i] соответствует условию condition if (condition(numbers[i])) { std::cout << numbers[i] << "\t"; }
При вызове функции action()
в нее можно передать нужное условие:
action(isEven, nums, n); action(isPositive, numbers, n);
В итоге программа выведет на экран числа из массива nums, которые соответствуют переданному условию:
Even numbers: -4 -2 0 2 4 Positive numbers: 1 2 3 4 5