Оценить:
 Рейтинг: 0

Обратные вызовы в C++

Год написания книги
2021
<< 1 2 3 4 5 6 7 8 9 10 ... 13 >>
На страницу:
6 из 13
Настройки чтения
Размер шрифта
Высота строк
Поля

}

private:

void onCallbackHandler(int eventID)  // (5)

{

//Do what is necessary

}

};

int main() // (6)

{

Initiator initiator;            // (7)

Executor executor(&initiator);  // (8)

initiator.run();                // (9)

//Wait finish

}

В строке 1 объявляется класс – исполнитель. В строке 2 объявляется конструктор с входным параметром – указателем на инициатор, здесь происходит настройка обратного вызова.[5 - Это необязательно делать в конструкторе, соответствующие операции можно выполнить после объявлений экземпляров инициатора и исполнителя в функции main. Однако инициализация в конструкторе представляется более удобной, потому что настройка вызова будет сделана сразу при объявлении экземпляра класса – исполнителя без дополнительных операций.]

В строке 3 объявлен статический метод как обработчик обратного вызова. Входными параметрами здесь являются информация вызова (в нашем случае это eventID) и указатель на контекст, в качестве которого выступает указатель на экземпляр класса. Внутри метода можно обращаться к содержимому класса, используя полученный указатель как квалификатор. Таким образом, прямо здесь можно реализовать код обработчика, а можно вызвать обычный (нестатический) метод класса (строка 4).

Далее, в строке 6 объявлена основная функция, в которой осуществляются все необходимые операции. В строке 7 объявлен класс-инициатор; в строке 8 объявлен класс- исполнитель, в конструктор передается указатель на инициатор; в строке 9 происходит запуск инициатора.

Особенностью реализации исполнителя с помощью указателя на статический метод является возможность работы с инициатором, предназначенным для указателей на функцию. В этом случае метод класса в качестве контекста должен принимать нетипизированный указатель с последующим приведением типов. Пример использования показан в Листинг 8, инициатор здесь используется из Листинг 1 п. 2.1.2.

Листинг 8. Исполнитель с указателем на статический метод класса для инициатора с нетипизированным контекстом

class Executor  // (1)

{

public:

Executor()    // (2)

{

setup(callbackHandler, this);

}

static void callbackHandler(int eventID, void* somePointer)    // (3)

{

//It will be called by initiator

Executor* executor = static_cast<Executor*>(somePointer);  // (4)

executor->onCallbackHandler(eventID);

}

private:

void onCallbackHandler(int eventID) // (5)

{

//Do what is necessary

}

};

int main()           // (6)

{

Executor executor; // (7)

run();             // (8)

//Wait finish

}

Настройка обратного вызова осуществляется в конструкторе (строка 2). В обработчике обратного вызова (строка 3) мы делаем приведение типов (строка 4), чтобы получить указатель на экземпляр класса. В главной функции (строка 6) происходит запуск инициатора.

2.2.4. Синхронный вызов

Реализация инициатора для синхронного вызова приведена в Листинг 9. Как видим, она практически полностью повторяет реализацию, рассмотренную в предыдущей главе, только в качестве указателя на контекст используется указатель на экземпляр класса.

Листинг 9. Инициатор для синхронного обратного вызова с указателем на статический метод класса

class Executor;

using ptr_callback_static = void(*) (int, Executor*);
<< 1 2 3 4 5 6 7 8 9 10 ... 13 >>
На страницу:
6 из 13