Указатели на функции часто используют в качестве аргументов функций.


Однако предпочтительнее использовать вариант 1.

Указатель на функцию может инициализироваться при определении. При этом должны совпадать тип и сигнатура. Аналогично при присваивании значений указателю и при вызове функций с помощью указателей.

В определении указателя на функцию тип возвращаемого значения и сигнатура должны совпадать с соответствующими типами и сигнатурами тех функций, адреса которых предполагается присваивать вводимому указателю при инициализации или с помощью оператора присваивания.

Не путать с описанием

Имя функции без скобок и параметров выступает в роли указателя на эту функцию и его значением является адрес размещения функции в памяти.

Иногда под сигнатурой функции подразумевают список типов ее параметров.

Каждая функция характеризуется типом возвращаемого значения, именем и сигнатурой. Сигнатура определяется количеством, порядком следования и типами параметров.

Указатель на функцию определяется следующим образом:

тип_функции(*имя_указателя)(спецификация_ параметров);

Например: int(*f1Ptr)(char) определяет указатель f1Ptr на функцию с параметром типа char, возвращающую значение типа int.

int* f1(char);

- это прототип функции с именем f1и параметром типасhar,возвращающей значение указателя типаint.

char* (*f2Ptr)(char*, int);

Это определение указателя f2Ptr на функцию с параметрами типа указатель на char и типа int, возвращающую значение типа указатель на char.

#include <iostream>

using namespace std;

void f1 (void)

{cout << "выполняется f1()\n";}

void f2 (void)

{cout << "выполняется f2()\n";}

void main()

{ setlocale(LC_ALL,".1251");

void (*ptr)(void); // ptr - указатель на функцию

ptr=f2; // присваивается адрес f2()

(*ptr)(); // вызов f2 по адресу

ptr=f1; // присваивается адрес f1()

(*ptr)(); // вызов f1 по адресу

ptr(); // вызов эквивалентен (*ptr)();

}

Результат выполнения:

выполняется f2()

выполняется f1()

выполняется f1()

В программе описан указатель ptr на функцию, и ему последовательно присваиваются адреса функций f1 и f2.

Формат вызова функции:

(*имя_указателя)(спиcок_фактических_параметров);

Значением имени_указателя служит адрес функции, а с помощью операции разыменования * обеспечивается обращение по адресу к этой функции. Ошибкой будет обращение

*ptr();

Ибо () имеют более высокий приоритет, чем*.

char f1(char){…} //определение функции

char f2(int){…} //определение функции

void f3(float){…} //определение функции

int* f4(char*){…} //определение функции

char (*pt1)(int); //указатель на функцию

char (*pt2)(int); //указатель на функцию

void (*pt3)(float)=f3;

//инициализированный указатель на функцию

pt1=f1; //ош-несоотв сигнатур

pt2=f3; //ош-несоотв типов и сигнатур

pt1=f4; //ош-несоотв типов

pt1=f2; //ok!

pt2=pt1; //ok!

char c=(*pt1)(44);//ok!

c=(*pt2)(’\t’);// ош-несоотв сигнатур

Пример вызова функций с помощью указателей:

 

#include <iostream>

using namespace std;

//функции одного типа с одинаковыми //сигнатурами

int add (int n, int m) {return n+m;}

int divi(int n, int m) {return n/m;}

int mult(int n, int m) {return n*m;}

int subt(int n, int m) {return n-m;}

void main()

{ setlocale(LC_ALL,".1251");

int (*par)(int, int);

// указатель на функцию

int a=6, b=2;

char c='+';

while (c!='0')

{ cout<<"знак операции или 0?\n";

cin>>c;

switch (c)

{case '0': break;

case '+': par=add; break;

case '-': par=subt; break;

case '*': par=mult; break;

case '/': par=divi; break;

default : cout <<

"неверная операция" << endl;

c ='1'; break;

}

if ((c!='1')&&(c!='0'))

cout << a << c << b << "="<< (*par)(a,b)<< endl;

//вызов по адресу

}

}

Вызывается функция по адресу, содержащемуся в указателе par следующим

образом:

(*par)(a,b); (1)

Альтернативная форма вызова через указатель подобна нормальному вызову функции:

par(a,b); (2)