Обратные вызовы в C++ | страница 56
Графически использование связывания продемонстрировано на Рис. 18. Пусть инициатор вызывает функцию 1, которая на вход принимает аргумент 1. Исполнитель реализует обратный вызов с помощью функции 2, которая принимает на вход два аргумента. Вместо функции 1 инициатору назначается объект связывания, который имеет перегруженный оператор вызова функции с сигнатурой 1. Указанный объект хранит дополнительный параметр, значение которому присваивается во время инициализации. Перегруженный оператор, в свою очередь, вызывает функцию 2, первому аргументу передает сохраненный параметр, а второму аргументу передает значение аргумента из функции 1. Таким образом, осуществляется перенаправление вызова из функции 1 в функцию 2.
Рис. 18. Перенаправление вызовов
Использование перенаправления вызовов представлено в Листинг 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 = 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), то будет вызвана функция, назначенная этому объекту, и этой функции будут переданы соответствующие аргументы.