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

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

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

void run(ptr_callback_static ptrCallback, Executor * contextData = nullptr)

{

int eventID = 0;

//Some actions

ptrCallback (eventID, contextData);

}

2.2.5. Преимущества и недостатки

Преимущества и недостатки реализации обратных вызовов с помощью указателя на статический метод класса приведены в Табл. 2.

Табл. 2. Преимущества и недостатки обратных вызовов с указателем на статический метод класса.

Простая реализация. Не сложнее, чем для указателей на функцию.

Совместим с инициатором в процедурном дизайне. Можно использовать для работы с системными API.

Инициатор хранит контекст исполнителя. Так же, как и в случае указателей на функцию, усложняет реализацию и способствует увеличению расхода памяти.

2.3. Указатель на метод-член класса

2.3.1. Концепция

В предыдущей главе мы рассматривали использование указателя на статический метод класса, в который в качестве контекста передавали указатель на экземпляр класса. А почему бы нам напрямую не вызвать метод-член класса, минуя прослойку в виде статического метода, из которого вызывается метод-член класса? Для этого нам понадобятся указатель на класс и указатель на метод.

Графическое изображение обратного вызова с помощью указателя на метод-член класса (далее – метод класса) представлено на Рис. 12. Исполнитель реализуется в виде класса, код упаковывается в метод класса, в качестве контекста выступает экземпляр класса. При настройке указатель на метод и указатель на класс как как аргументы сохраняются в инициаторе. Инициатор осуществляет обратный вызов посредством вызова метода, передавая ему требуемую информацию. Контекст здесь передавать не нужно, поскольку внутри метода доступно все содержимое класса.

Рис. 12. Реализация обратного вызова с помощью указателя на метод-член класса

2.3.2. Инициатор

Реализация инициатора приведена в Листинг 10.

Листинг 10. Инициатор с указателем на метод-член класса

class Executor;  // (1)

class Initiator  // (2)

{

public:

using ptr_callback_method = void(Executor::*)(int);  // (3)

void setup(Executor* argCallbackClass, ptr_callback_method argCallbackMethod)    // (4)

{

ptrCallbackClass = argCallbackClass; ptrCallbackMethod = argCallbackMethod;  // (5)

}

void run()  // (6)

{

int eventID = 0;

//Some actions

(ptrCallbackClass->*ptrCallbackMethod)(eventID);  // (7)

}

private:

Executor* ptrCallbackClass = nullptr;             // (8)

ptr_callback_method ptrCallbackMethod = nullptr;  // (9)

};

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

2.3.3. Исполнитель

Реализация исполнителя приведена в Листинг 11.

Листинг 11. Исполнитель с указателем на метод-член класса

class Executor                       // (1)

{

public:

void callbackHandler(int eventID)  // (2)

{

//It will be called by initiator

}
<< 1 ... 3 4 5 6 7 8 9 10 11 ... 13 >>
На страницу:
7 из 13