Обратные вызовы в C++ | страница 56



, которые при необходимости могут сохраняться в std::function подобно обычным функциональным объектам.

Графически использование связывания продемонстрировано на Рис. 18. Пусть инициатор вызывает функцию 1, которая на вход принимает аргумент 1. Исполнитель реализует обратный вызов с помощью функции 2, которая принимает на вход два аргумента. Вместо функции 1 инициатору назначается объект связывания, который имеет перегруженный оператор вызова функции с сигнатурой 1. Указанный объект хранит дополнительный параметр, значение которому присваивается во время инициализации. Перегруженный оператор, в свою очередь, вызывает функцию 2, первому аргументу передает сохраненный параметр, а второму аргументу передает значение аргумента из функции 1. Таким образом, осуществляется перенаправление вызова из функции 1 в функцию 2.


Рис. 18. Перенаправление вызовов


Использование перенаправления вызовов представлено в Листинг 60.

Листинг 60. Перенаправление вызовов

>#include 


>void NativeHandler(int eventID)  // (1)

>{

>  //here eventID is 10

>}


>void AnotherHandler(int contextID, int eventID)  // (2)

>{

>  //here eventID is 1, contextID is 10;

>}


>int main()

>{

>  int eventID = 1; int contextID = 10;


>  std::function fnt;  // (3)

>  fnt = NativeHandler;           // (4)

>  fnt(eventID);                  // (5) NativeHandler will be called


>  fnt = std::bind(AnotherHandler, contextID, std::placeholders::_1);  // (6)

>  fnt(eventID);  // (7) AnotherHandler will be called

>}


В строке 1 объявлен исходный обработчик, в строке 2 – обработчик, в который будет перенаправляться вызов. В строке 3 объявлен универсальный аргумент с исходной сигнатурой. В строке 4 аргументу назначена функция, которая будет вызвана при выполнении вызова 5.

В строке 6 вызывается функция bind, которая из переданных аргументов формирует объект связывания. На вход std::bind передается имя новой функции-обработчика и аргументы, которые будут передаваться в эту функцию. Первому аргументу здесь будет назначено значение contextID, а второму аргументу будет назначено значение 1-го по порядку аргумента из исходной функции. Здесь конструкция std::placeholders определяет номер аргумента в исходной функции, который будет подставлен в качестве аргумента в перенаправляемую функцию.

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