- •Лекция №10 Тема: Строки.
- •Функции работы со строками из библиотеки обработки строк
- •Пример 4.
- •Пример 5
- •Пример на многомерные динамические массивы
- •Указатели на функции
- •Пример №1
- •Результат выполнения программы:
- •Результат выполнения программы
- •Пример №3
- •Пример №2
- •Результаты выполнения программы
Указатели на функции
Прежде чем вводить указатель на функцию, напомним, что каждая функция характеризуется типом возвращаемого значения, именем, количеством, порядком следования и типами параметров.
При использовании имени функции без последующих скобок и параметров имя функции выступает в качестве указателя на эту функцию, и его значением служит адрес размещения функции в памяти. Это значение адреса может быть присвоено другому указателю, и затем уже этот новый указатель можно применять для вызова функции. Однако в определении нового указателя должен быть тот же тип, что и возвращаемое функцией значение, то же количество, порядок следования и типы параметров. Указатель на функцию определяется следующим образом:
тип функции (*имя_указателя)(спецификация_параметров);
Например: int(*func1ptr) (char); — определение указателя func1ptr на функцию с параметром типа char, возвращающую значение типа int.
Если приведенную синтаксическую конструкцию записать без первых круглых скобок, то есть в виде int *fun(char); то компилятор воспримет ее как прототип некой функции с именем fun и параметром типа char, возвращающей значение указателя типа int *.
Второй пример: char * (*func2Ptr) (char *, int); - определение указателя func2Ptr на функцию с параметрами типа указатель на char и типа int, возвращающую значение типа указатель на char.
В определении указателя на функцию тип возвращаемого значения и сигнатура (типы, количество и последовательность параметров) должны совпадать с соответствующими типами и сигнатурами тех функций, адреса которых предполагается присваивать вводимому указателю при инициализации или с помощью оператора присваивания. В качестве простейшей иллюстрации — небольшой пример:
Пример №1
/*Пример определения и использования
указателей на функции
*/
#include<iostream.h>
// описание функции f1
void f1(void)
{
cout<<"\n Выполняется f1()";
}
// описание функции f2
void f2(void)
{
cout<<"\n Выполняется f2()";
}
void main()
{
// объявление указателя на функцию,
void (*ptr)(void); // ptr - указатель на функцию
ptr = f2; // ptr инициализируется адресом f2()
(*ptr)(); // вызов f2() по ее адресу
ptr = f1; // присваивается адрес f1()
(*ptr)(); // вызов f1() по ее адресу
ptr(); // вызов эквивалентен (*ptr)();
}
Результат выполнения программы:
Выполняется f2()
Выполняется f1()
Выполняется f1()
В программе описан указатель ptr на функцию, и ему последовательно присваиваются адреса функции f2 и fl. Обратите внимание на форму вызова функции с помощью указателя на функцию:
(*имя_укаэателя)(список_фактических_параметров);
Значением имени_указателя служит адрес функции, а с помощью операции разыменования * обеспечивается обращение по адресу к этой функции. Однако будет ошибкой записать вызов функции без скобок в виде *ptr(); Дело в том, что операция () имеет более высокий приоритет, нежели операция обращения по адресу *. Следовательно, в соответствии с синтаксисом будет вначале сделана попытка обратиться к функции ptr(). И уже к результату будет отнесена операция разыменования, что будет воспринято как синтаксическая ошибка.
При определении указатель на функцию может быть инициализирован. В качестве инициализирующего значения должен использоваться адрес функции, тип и сигнатура(типы, количество и последовательность параметров) которой соответствуют определяемому указателю.
При присваивании указателей на функции также необходимо соблюдать соответствие типов возвращаемых значении функции и сигнатур для указателей правой и левой частей оператора присваивания. То же справедливо и при последующем вызове функций с помощью указателей, т.е. типы и количество фактических параметров, используемых при обращении к функции по адресу, должны соответствовать формальным параметрам вызываемой функции.
Следующая программа иллюстрирует гибкость механизма вызовов функций с помощью указателей.
