Указатели на функции как параметры
Указатели на функции - незаменимое средство языков С и С++, когда объектами обработки должны служить функции. Например, создавая процедуры для вычисления определенного интеграла задаваемой пользователем функции или для построения таблицы значений произвольной функции, нужно иметь возможность передавать в программы функции. Удобнее всего организовать связь между функцией, реализующей метод обработки (например, численный метод интегрирования), и той функцией, для которой этот метод нужно применить, через аппарат параметров, в число которых входят указатели на функции.
Рассмотрим задачу вычисления корня функции f(x) на интервале локализации [А; В] для иллюстрации особенностей применения указателя функции в качестве параметра. Численный метод (деление пополам интервала локализации) оформляется в виде функции со следующим заголовком:
float root(указатель_на_функцию, float A, float В, float EPS);
Здесь А - нижняя граница интервала локализации корня; B - верхняя граница того же интервала; EPS - требуемая точность определения корня. Введем тип "указатель на функцию", для которой нужно определить корень:
typedef float(*pointPunc)(float);
Теперь можно определить функцию для вычисления корня заданной функции с указателем pointPunc. Прототип функции будет таким:
float root(pointPunc F, float A, float B, float EPS);
Приведем тестовую программу для определения с помощью root() корня функции у = х2 - 1 на интервале [0, 2]:
//RAZN3_1.СРР - указатель функции как параметр функции.
#include <iostream.h>
#include <stdlib.h> // Для функции exit().
// Определение типа указателя на функцию:
typedef float (*pointFunc)(float);
// Определение функции для вычисления корня:
float root(pointFunc F, float A, float B, float EPS)
{
float x, y, c, Fx, Fy, Fc;
x = A; y = B;
Fx = (*F)(x); // Значение функции на левой границе.
Fy = (*F)(y); // Значение функции на правой границе.
if (Fx * Fy > 0.0)
{
cout << " Неверен интервал локализации";
exit(1); // Аварийное завершение программы.
}
do
{
c = (y - x)/2; // Центр интервала локализации.
Fc = (*F)(c); // Значение функции в с.
if (Fc * Fx > 0) { x = c; Fx = Fc; }
else { y = c; Fy = Fc; }
} while (Fc != 0 && y - x > EPS);
return c;
}
#include <math.h>
// Определение тестовой функции у = х * х - 1:
float testfunc(float x)
{ return x * x - 1; }
void main()
{
float root(pointFunc, float, float, float); // Прототип.
float result;
result = root(testfunc, 0.0, 2.0, 1e-5);
cout << " Корень тестовой функции: " << result;
}
Текст этой программы можно взять здесь.
Результат выполнения программы:
Корень тестовой функции: 1
Заметим, что, помимо использования в качестве параметра, указатель на функцию может быть еще и типом возвращаемого значения. Например:
И здесь использование директивы typedef делает объявление понятнее. Объявив PF с помощью typedef, мы видим, что ff() возвращает указатель на функцию:
// Использование директивы typedef делает// объявления более понятнымиtypedef int (*PF)(int*, int);PF ff(int);Типом возвращаемого значения функции не может быть тип функции. В этом случае выдается ошибка компиляции. Например, нельзя объявить ff() таким образом:
// typedef представляет собой тип функцииtypedef int func(int*, int);func ff(int); // ошибка: тип возврата ff() - функция
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&