Виталий Ткаченко - Обратные вызовы в C++

Тут можно читать онлайн Виталий Ткаченко - Обратные вызовы в C++ - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming, издательство Array SelfPub.ru, год 2021. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.

Виталий Ткаченко - Обратные вызовы в C++ краткое содержание

Обратные вызовы в C++ - описание и краткое содержание, автор Виталий Ткаченко, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru
В практике разработки ПО зачастую встает задача динамической модификации программного кода в зависимости от текущих или настраиваемых значений параметров. Для решения этой задачи широко используются обратные вызовы. В языке C++ обратные вызовы реализуются различными способами, и далеко не всегда очевидно, какой из них лучший для конкретной ситуации. В книге рассмотрены теоретические и практические аспекты организации обратных вызовов, проанализированы достоинства и недостатки различных реализаций, выработаны рекомендации по выбору в зависимости от требований к проектируемому ПО. В первую очередь книга предназначена для программистов среднего (middle) уровня, т.е. тех, кто уже достаточно хорошо знает язык C++, но хотел бы расширить и углубить свои знания в области проектирования и дизайна. В определенной степени она также будет интересна опытным разработчикам, с одной стороны, как систематизация знаний, с другой стороны, как источник идей и методов для решения практических задач.

Обратные вызовы в C++ - читать онлайн бесплатно полную версию (весь текст целиком)

Обратные вызовы в C++ - читать книгу онлайн бесплатно, автор Виталий Ткаченко
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

void operator() (int eventID) {}

};

void ExternalHandler(int eventID, void* somePointer) {} // (2)

int main()

{

Executor executor; // (3)

int capturedValue = 0;

// (4) Pointer to the external function

using PtrExtFunc = void(*) (int, void*); // (5)

using CallbackExtFunction = CallbackConverter; // (6)

Initiator initExtFunction; // (7)

initExtFunction.setup(CallbackExtFunction(ExternalHandler, &executor)); // (8)

// (9) Pointer to the static method

using PtrStaticMethod = void(*) (int, Executor*); // (10)

using CallbacStaticMethod = CallbackConverter; // (11)

Initiator initStaticMethod; // (12)

initStaticMethod.setup(CallbacStaticMethod(Executor::staticCallbackHandler, &executor)); // (13)

// (14) Pointer to the class member method

using PtrMethod = void(Executor::*)(int); // (15)

using CallbackMemberMethod = CallbackConverter; // (16)

Initiator initMemberMethod; // (17)

initMemberMethod.setup(CallbackMemberMethod(&executor, &Executor::callbackHandler)); // (18)

// (19) Functional object

Initiator initFunctionObject; // (20)

initFunctionObject.setup(executor); // (21)

// (22) Lambda-expression

auto lambda = [capturedValue](int eventID) {/*Body of lambda*/}; // (23)

Initiator initLambda ( lambda); // (24)

}

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

В строке 4 показан обратный вызов через указатель на функцию. Объявлен тип указателя на функцию 5, тип функционального объекта для преобразования вызова 6, инстанциирование шаблона инициатора соответствующим типом 7, настройка инициатора 8. Запуск инициатора (метод run) не показан, чтобы не загромождать описание.

В строке 9 показан обратный вызов через указатель на статический метод класса. Похоже на предыдущий случай, только в качестве контекста используется указатель на класс. Объявлен тип указателя на статический метод 10, тип функционального объекта для преобразования вызова 11, инстанциирование инициатора соответствующего типа 12, настройка инициатора 13.

В строке 14 показан обратный вызов через указатель на метод-член класса. Объявлен тип указателя на метод 15, тип функционального объекта для преобразования вызова 16, инстанциирование инициатора соответствующим типом 17, настройка инициатора 18.

В строке 19 показан обратный вызов с помощью функционального объекта. Инстанциирование инициатора объявлено в строке 20, настройка инициатора – в строке 21.

В строке 22 показан обратный вызов с помощью лямбда-выражения. В строке 23 объявлено лямбда-выражение, которое запоминается в соответствующей переменной. В строке 24 инстанциирован инициатор типом лямбда-выражения. Инициатору в конструкторе передается переменная – объект указанного выражения.

Для случаев, когда используется преобразование вызовов (объявления 4, 9 и 14), можно использовать сокращенные объявления без использования промежуточных деклараций. Код в этом случае получается более компактным, но менее понятным (см. Листинг 44).

Листинг 44. Компактный способ объявлений при использовании преобразования вызовов

int main

{

Executor executor;

// (4) Pointer to the external function

Initiator> initExtFunction;

initExtFunction.setup(CallbackConverter(ExternalHandler, &executor));

// (9) Pointer to the static method

Initiator> initStaticMethod;

initStaticMethod.setup(CallbackConverter (int, Executor*), Executor*> (Executor::staticCallbackHandler, &executor));

// (14) Pointer to the class member method

Initiator> initMemberMethod;

initMemberMethod.setup(CallbackConverter (&executor, &Executor::callbackHandler));

}

Итак, как мы видим, для каждого типа аргумента обратного вызова нам приходится объявлять соответствующий инициатор. Может быть, можно сделать так, чтобы инициатор умел работать с различными типами аргументов? Для этого нужно спроектировать универсальный аргумент, чем мы и займемся в следующей главе.

4.5. Универсальный аргумент

4.5.1. Динамический полиморфизм

Для реализации универсального аргумента прежде всего необходимо обеспечить динамический полиморфизм, т. е. аргумент должен изменять свой тип в зависимости от задаваемого значения 21 21 Термин «динамический полиморфизм» означает, что полиморфизм реализуется во время выполнения программы. В противоположность этому, статический полиморфизм реализуется на этапе компиляции программы. В строгом смысле этого термина динамический полиморфизм в C++ нереализуем, поскольку это язык со статической типизацией. Однако его можно смоделировать с помощью наследования и шаблонов, о чем пойдет речь далее. .

Как решается указанная задача в объектно-ориентированном дизайне? Объявляется базовый абстрактный класс, в котором описывается интерфейс в виде набора чисто виртуальных методов. Новый тип создается путем создания наследуемого класса, в котором объявляются нужные переменные и переопределяются методы. При инициализации создается класс нужного типа, и он сохраняется в переменной – указателе на базовый класс. Мы будем использовать аналогичный подход, только наследуемые типы будут создаваться динамически, используя параметры шаблона. Указанная техника называется «стирание типов»: при назначении нового типа аргумента предыдущий сохраненный уничтожается, и его место занимает новый 22 22 Для фундаментального изучения техники стирания типов можно порекомендовать книгу «Пикус Ф.Г. Идиомы и паттерны проектирования в современном С++», в которой указанной технике посвящена отдельная глава. .

Графическое изображение стирания типов изображено на Рис. 17. Рассмотрим начальное состояние а), показанное в верхней части рисунка. Имеется некоторый класс, назовем его UniArgument. В этом классе объявлен перегруженный оператор вызова функции 2 . Также здесь имеется указатель 3 типа Callable*, который указывает на соответствующий экземпляр класса Callable. Класс Callable 4 объявлен внутри UniArgumentи имеет виртуальный перегруженный оператор вызова функции с пустой реализацией.

Когда в UniArgumentпроисходит вызов 1 перегруженного оператора 2 , последний через указатель 3 вызывает виртуальный перегруженный оператор класса Callable.

В нижней части рисунка б) показано, как назначается новый тип. Объявляется перегруженный оператор присваивания 10 , на входе он принимает аргумент обратного вызова 8. При вызове этого оператора старый экземпляр класса 4 , на который указывал указатель 3 , уничтожается в 11 , а вместо него создается новый класс CallableObject 5 , который наследуется от Callable. Внутри класса имеется поле 7, в которое записывается переданный аргумент 8 , тип этого поля совпадает с типом аргумента. В CallableObjectпереопределяется оператор вызова функции 6 , который, в свою очередь, осуществляет вызов через сохраненный аргумент 7 . Теперь указатель 3 указывает на новый созданный CallableObject, и при вызове 1 перегруженного оператора 2 будет вызываться перегруженный оператор указанного класса, который и выполнит обратный вызов.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Виталий Ткаченко читать все книги автора по порядку

Виталий Ткаченко - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




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


Отзывы читателей о книге Обратные вызовы в C++, автор: Виталий Ткаченко. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x