Указатели на функции и класс function

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

Указатели на функции

Объявление указателя на функцию выглядит так:

<Тип> (*<Название указателя>)([<Тип 1>[, ..., <Тип N>]]);

Чтобы присвоить указателю адрес функции, необходимо указать название функции без параметров и круглых скобок справа от оператора =. Типы параметров указателя и функции должен совпадать. Пример объявления указателя и присваивания адреса функции:

int (*pfunc)(int, int) = nullptr;
pfunc = sum;

Вызвать функцию через указатель можно так:

int x = pfunc(30, 10); // Аналогично x = sum(10, 20);

Или так:

int y = (*pfunc)(30, 10);

Пример объявления указателя, вызова функции через указатель и передачи указателя в качестве параметра функции приведен в листинге 12.24.

Листинг 12.24. Указатели на функции

#include <iostream>

void print_ok();
int add(int x, int y);
int sub(int x, int y);
int func(int x, int y, int (*pfunc)(int, int));

int main() {
   // Объявление указателей на функции
   void (*pf1)() = nullptr;
   int (*pf2)(int, int) = nullptr;
   // Присваивание адреса функции
   pf1 = print_ok;
   pf2 = add;
   // Вызов функций через указатели
   pf1();                                      // OK
   std::cout << pf2(30, 10) << std::endl;      // 40
   // Передача указателя на функцию
   // в качестве значения параметра
   std::cout << func(10, 5, pf2) << std::endl; // 15
   std::cout << func(10, 5, add) << std::endl; // 15
   std::cout << func(10, 5, sub) << std::endl; // 5
   return 0;
}
void print_ok() {
   std::cout << "OK" << std::endl;
}
int add(int x, int y) {
   return x + y;
}
int sub(int x, int y) {
   return x - y;
}
int func(int x, int y, int (*pfunc)(int, int)) {
   return pfunc(x, y);
}

Создание псевдонима с помощью оператора typedef выполняется так:

typedef int (*func)(int, int);
func pf = add;
std::cout << pf(20, 10) << std::endl;       // 30

Начиная со стандарта C++11, вместо оператора typedef можно использовать оператор using:

using func = int (*)(int, int);
func pf = add;
std::cout << pf(40, 10) << std::endl;       // 50

Класс function

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

#include <functional>

Создание объекта осуществляется по следующим схемам:

std::function<Сигнатура_функции> func1(Название_функции);
std::function<Сигнатура_функции> func2 = Название_функции;
std::function<Сигнатура_функции> func3;
func3 = Название_функции;
std::function<Сигнатура_функции> func4 = nullptr;
func4 = Название_функции;

Внутри угловых скобок указывается сигнатура функции, состоящая из типа возвращаемого значения и типов параметров через запятую внутри круглых скобок, например, void() или int(int,int). Вызов функции осуществляется как обычно, с помощью круглых скобок, внутри которых через запятую указываются передаваемые значения. Если объект хранит нулевой указатель и при этом производится вызов функции, то генерируется исключение bad_function_call.

Пример использования класса function приведен в листинге 12.25.

Листинг 12.25. Класс function

#include <iostream>
#include <functional>

void print_ok();
void print(const char *str);
int sum(int x, int y);
int func(int x, int y, std::function<int(int,int)> f);

int main() {
   // Создание объектов
   std::function<void()> func1;
   func1 = print_ok;
   std::function<void(const char*)> func2(print);
   std::function<int(int,int)> func3 = nullptr;
   func3 = sum;
   // Вызов функций
   func1();                                    // OK
   func2("1");                                 // 1
   std::cout << func3(30, 10) << std::endl;    // 40
   // Передача в функцию
   std::cout << func(10, 5, sum) << std::endl; // 15
   return 0;
}
void print_ok() {
   std::cout << "OK" << std::endl;
}
void print(const char *str) {
   std::cout << str << std::endl;
}
int sum(int x, int y) {
   return x + y;
}
int func(int x, int y, std::function<int(int,int)> f) {
   return f(x, y);
}

Учебник C++ (Qt Creator и MinGW)
Учебник C++ (Qt Creator и MinGW) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов