Указатель на функцию фактически представляет некоторый тип, и функция также может иметь параметр, который представляет тип указателя на функцию. Таким образом, мы можем через параметр на функцию передавать в одну функцию другую. То есть функция может быть аргументом другой функции.
Рассмотрим пример:
#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