Обратные вызовы в C++ | страница 57
Аналогичным образом может быть объявлено перенаправление вызовов для методов-членов класса, но здесь должно соблюдаться следующее правило: первому аргументу новой функции должен быть назначен первый аргумент исходной функции, потому что он определяет экземпляр класса, для которого вызывается метод. Пример приведен в Листинг 61.
>#include
>class CallbackHandler
>{
>public:
> void NativeHandler(int eventID)
> {
> //eventID = 1;
> }
> void AnotherHandler(int contextID, int eventID)
> {
> //eventID = 1, contextID = 10;
> }
>};
>int main()
>{
> using namespace std::placeholders; // (1)
> int eventID = 1; int contextID = 10;
> CallbackHandler handler;
> std::function
> fnt = &CallbackHandler::NativeHandler;
> fnt(&handler, eventID); // NativeHandler will be called
> fnt = std::bind(&CallbackHandler::AnotherHandler, _1, contextID, _2); // (2)
> fnt(&handler, eventID); // AnotherHandler will be called
>}
Здесь в строке 1 мы использовали using namespace, что сокращает объявление позиций аргументов: как видно из строки 2, мы сразу пишем позицию без использования std::placeholders, что значительно компактнее и проще для восприятия. Здесь в исходной функции присутствует неявный параметр с номером 1, который определяет экземпляр класса. Этот параметр назначается первому (неявному) параметру новой функции, а второй параметр исходной функции eventID назначается последнему параметру новой функции.
В общем случае могут быть 4 варианта перенаправления вызовов:
• из функции в функцию (пример в Листинг 60);
• из функции в метод класса;
• из метода класса в другой метод этого же класса (пример в Листинг 61);
• из метода класса в метод другого класса;
• из метода класса в функцию.
Реализация указанных вариантов, по сути, одинакова, отличаются только объявления связывания. Сведем эти объявления в таблицу (Табл. 13).
Табл. 13. Связывания для различных вариантов перенаправления вызовов.
Теперь перенаправление вызовов в исполнителе не представляет сложности: при настройке вместо объекта вызова нужно всего лишь подставить необходимое связывание. Пример для варианта «функция – функция» приведен в Листинг 62, здесь используется инициатор из Листинг 53.
>void NativeHandler(int eventID)
>{
> //here eventID is 10
>}
>void AnotherHandler(int contextID, int eventID)
>{
> //here eventID is 10, contextID is 1;