Указатели на функции как параметры

Указатели на функции - незаменимое средство языков С и С++, когда объектами обработки должны служить функции. Например, создавая процедуры для вычисления определенного интеграла задаваемой пользователем функции или для построения таблицы значений произвольной функции, нужно иметь возможность передавать в программы функции. Удобнее всего организовать связь между функцией, реализующей метод обработки (например, численный метод интегрирования), и той функцией, для которой этот метод нужно применить, через аппарат параметров, в число которых входят указатели на функции.

Рассмотрим задачу вычисления корня функции 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


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

int (*ff(int))(int*, int);ff() объявляется как функция, имеющая один параметр типа int и возвращающая указатель на функцию типаint (*)(int*, int);

И здесь использование директивы typedef делает объявление понятнее. Объявив PF с помощью typedef, мы видим, что ff() возвращает указатель на функцию:

// Использование директивы typedef делает// объявления более понятнымиtypedef int (*PF)(int*, int);PF ff(int);

Типом возвращаемого значения функции не может быть тип функции. В этом случае выдается ошибка компиляции. Например, нельзя объявить ff() таким образом:

// typedef представляет собой тип функцииtypedef int func(int*, int);

func ff(int); // ошибка: тип возврата ff() - функция

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&