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

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

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

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

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

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

Интервал:

Закладка:

Сделать

Итак, универсальный аргумент практически готов. Нам осталось реализовать оператор копирования, оператор присваивания и некоторые другие операции. Но мы этим заниматься не будем: разработчики стандартной библиотеки уже обо всем позаботились, поэтому темой следующей главы будет обзор инструментов STL для организации обратных вызовов 24 24 «Зачем же мы тогда разрабатывали универсальный аргумент, если в STL все уже давно реализовано?» – может воскликнуть рассерженный читатель. Ну, во-первых, грамотный разработчик отличается от обычного разработчика тем, что он не только знает, как применять те или иные инструменты, но еще и понимает, как они работают. И, во-вторых, рассмотренные методы используются не только в проектировании обратных вызовов, они могут использоваться при решении самых различных задач. .

4.6. Использование стандартной библиотеки

4.6.1. Организация вызовов

В стандартной библиотеке имеется полиморфный класс – оболочка std::function, предназначенная для организации вызовов различных типов. Этот класс идеально подходит на роль универсального аргумента. Кроме рассмотренных техник стирания типа и настройки сигнатуры, в нем реализовано множество других вещей: конструктор копирования, оператор присваивания, поддержка указателей на методы класса, проверка настройки аргумента, локальный буфер для хранения аргумента и многое другое. Мы не будем рассматривать реализацию std::function, потому что, во-первых, она достаточно сложная, а, во-вторых, может изменяться в зависимости от версии и платформы. При желании читатель сможет сделать это самостоятельно, проанализировав исходный код, мы же сосредоточимся на практическом использовании класса-оболочки.

Насколько сложна реализация std::function, настолько же просто ее использование. По аналогии с универсальным аргументом, рассмотренном в предыдущей главе, достаточно объявить экземпляр класса с нужной сигнатурой, после чего ему можно назначать различные объекты вызовов (Листинг 51).

Листинг 51. Использование std::function

void External(int eventID) {};

int main()

{

struct Call

{

void operator() (int eventID) {};

} objectCall;

std::function fnt;

fnt = External;

fnt = objectCall;

fnt = [](int evetID) {};

fnt(0);

}

Полезной особенностью std::functionявляется проверка настройки объекта вызова. Если объект не настроен, т. е. не было ни одного присваивания, то при попытке вызова будет выброшено исключение. Проверить, настроен ли объект, можно с помощью перегруженного оператора bool, пример приведен в Листинг 52.

Листинг 52. Проверка настройки аргумента

int main()

{

std::function fnt;

fnt(0); //Error: argument is not set. Exception will be thrown

fnt = [](int) {};

fnt(0); //Ok, argument is set

//Check if the argument is set

if (fnt)

{

fnt(0);

}

}

4.6.2. Инициатор с универсальным аргументом

Для реализации инициатора с универсальным аргументом необходимо для хранения аргумента объявить соответствующую класс-оболочку std::function(Листинг 53).

Листинг 53. Инициатор с оболочкой std::function

class Initiator // (1)

{

public:

template

void setup(const CallbackArgument& argument) // (2)

{

callbackHandler = argument;

}

void run()

{

int eventID = 0;

//Some actions

callbackHandler(eventID);

}

private:

std::function callbackHandler; // (3)

};

Если сравнить реализацию инициатора с фиксированным типом аргумента (Листинг 37 п. 4.4.1) с приведенной, то можно заметить следующие отличия. В первом случае инициатор является шаблоном, здесь он объявляется обычным способом. Далее, хранимый аргумент 3 не является переменной типа, задаваемого параметром шаблона, он объявлен как универсальный аргумент std::function. Метод настройки 2 объявлен как шаблон, параметром которого является тип назначаемого аргумента.

Описанный инициатор не работает с указателями на функцию и на метод класса: в первом случае необходимо передавать контекст, во втором случае необходимо передавать указатель на экземпляр класса и использовать другой синтаксис для вызова. Как уже рассматривалось в п. 4.2.2, в этих случаях необходимо преобразование вызовов. Однако, поскольку в универсальном аргументе сигнатура может настраиваться, в объекты преобразования также нужно ввести поддержку настройки сигнатуры.

4.6.3. Преобразование с настройкой сигнатуры

В п. 4.2.2 реализованы объекты преобразования, которые работали с фиксированной сигнатурой. Используя технику, описанную в Листинг 47 п. 4.5.2, модифицируем их таким образом, чтобы сигнатуру можно было настроить. Для этого в параметрах шаблона вместо задания типов указателей на функцию будем задавать параметры, определяющие сигнатуру, а типы указателей будем выводить из этих параметров.

Рассмотрим вначале указатели на функцию (Листинг 54).

Листинг 54. Преобразование вызовов с настройкой сигнатуры для указателей на функцию

template // (1)

class CallbackConverter;

template // (2)

class CallbackConverter // (3)

{

public:

using Function = Return(*)(Context, ArgumentList…); // (4)

CallbackConverter(Function argFunction = nullptr, Context argContext = nullptr) // (5)

{

ptrFunction = argFunction; context = argContext;

}

Return operator() (ArgumentList… arguments) // (6)

{

ptrFunction(context, arguments…); // (7)

}

private:

Function ptrFunction; // (8)

Context context; // (9)

};

В строке 1 вводится общая специализация шаблона. В строке 2 объявляется специализация для указателей на функцию, в которой задается тип передаваемого контекста и параметры сигнатуры. В строке 4 выводится тип указателя. В конструкторе 5 осуществляется настройка указателей. В перегруженном операторе 6 осуществляется вызов 7, в который передаются соответствующие аргументы.

Аналогично выполняется специализация для вызова методов класса (Листинг 55).

Листинг 55. Преобразование вызовов с настройкой сигнатуры для указателей на метод класса.

template // (1)

class CallbackConverter // (2)

{

public:

using MemberPointer = Return(ClassType::*)(ArgumentList…); // (3)

CallbackConverter(MemberPointer methodPointer = nullptr, ClassType* classPointer = nullptr) // (4)

{

ptrClass = classPointer; ptrMethod = methodPointer;

}

Return operator()(ArgumentList… arguments) // (5)

{

(ptrClass->*ptrMethod)(arguments…); // (6)

}

private:

ClassType* ptrClass; // (7)

MemberPointer ptrMethod; // (8)

};

Реализация практически повторяет предыдущую, за исключением того, что в объявлениях типов сигнатуры добавляется класс (строки 2 и 3), а перегруженный оператор вызывает метод класса (строка 6).

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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