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

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

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

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

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

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

Интервал:

Закладка:

Сделать

thread_local ControlPointer g_SensorControl(sensor::ISensorControl::createControl());

6.3.5. Настройка драйвера

В исходной реализации в начале работы мы создавали необходимый класс драйвера, который затем передавали интерфейсному классу (Листинг 107). Но в интерфейсах системных API мы классы использовать не можем, как поступить в этом случае? Можно предложить следующее решение: класс драйвера создавать внутри API, а в функцию настройки передавать идентификатор, в соответствии с которым будет создан соответствующий драйвер (Листинг 108).

Листинг 107. Настройка драйвера в исходной реализации

ISensorControl sensorControl = ISensorControl::createControl;

DriverPointer driver = IDriver::createDriver(DRIVER_SIMULATION);

driver->initialize();

sensorControl->assignDriver(driver);

Листинг 108. Настройка драйвера в системном API (SensorLib.h)

thread_local sensor::DriverPointer g_DriverSimulation; // (1)

thread_local sensor::DriverPointer g_DriverUSB; // (2)

thread_local sensor::DriverPointer g_DriverEthernet; // (3)

void CreateDriver(sensor::DriverType driverType, sensor::DriverPointer& driverPointer) // (4)

{

if (!driverPointer)

{

driverPointer = sensor::IDriver::createDriver(driverType);

driverPointer->initialize();

}

g_SensorControl->assignDriver(driverPointer);

}

ErrorCode assignDriver(DriverType driverType) // (5)

{

ErrorCode error = ERROR_NO;

try

{

EnumConverter conv;

conv.convert (driverType, {sensor::DriverType::Simulation, sensor::DriverType::Usb, sensor::DriverType::Ethernet}); // (6)

if (conv.error())

{

return ERROR_INVALID_ARGUMENT;

}

switch (conv.result()) // (7)

{

case sensor::DriverType::Simulation:

{

CreateDriver(sensor::DriverType::Simulation, g_DriverSimulation);

}

break;

case sensor::DriverType::Usb:

{

CreateDriver(sensor::DriverType::Usb, g_DriverUSB);

}

break;

case sensor::DriverType::Ethernet:

{

CreateDriver(sensor::DriverType::Ethernet, g_DriverEthernet);

}

break;

}

}

catch (sensor::sensor_exception& e)

{

error = static_cast(e.code());

}

return error;

}

В строках 1–3 объявляются указатели для хранения классов всех возможных типов драйверов. В строке 4 объявлена вспомогательная функция для создания драйвера. Эта функция проверяет, создан ли драйвер соответствующего типа, при необходимости создает, инициализирует и передает его в интерфейсный класс.

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

В функции API для задания типа драйвера используются числовые значения, а в интерфейсном классе используются перечисления C++. Для того, чтобы сконвертировать числовое значение в перечисление, используется вспомогательный класс EnumConverter(Листинг 109)

Листинг 109. Конвертер числовых значений в перечисление (EnumConverter.h)

template // (1)

class EnumConverter

{

public:

template // (2)

void convert(ConvValueType value, std::initializer_list list) // (3)

{

isError_ = true;

for (Enum item : list) // (4)

{

if (static_cast(item) == value) // (5)

{

result_ = item; // (6)

isError_ = false;

break;

}

}

};

bool error() const { return isError_; }

Enum result() const { return result_; }

private:

bool isError_;

Enum result_;

};

В строке 1 объявлен шаблонный класс, параметром которого является тип перечисления. Конвертация происходит в функции 2, которая объявлена в виде шаблона, параметром шаблона является тип числового значения для конвертации. Функция принимает число, которое должно быть сконвертировано, а также список значений перечисления (строка 3). Реализация пробегает по всем элементам списка (строка 4) и, если какой-то из элементов списка перечисления равен переданному значению, запоминает это значение перечисления в качестве результата (строки 5,6).

6.3.6. Обратные вызовы

Касательно обратных вызовов мы имеем следующую ситуацию. В системном API контекст вызова передается с помощью указателей на данные, по-другому организация передачи контекста здесь невозможна (см. п. 2.1.2). В интерфейсном классе указатель на данные не используется, поскольку в C++ имеется множество гораздо более изящных способов передачи контекста. Вот тут-то нам и понадобится перенаправление вызовов (см. п. 4.6.2). Реализация одной из интерфейсных функций API, использующей перенаправление вызовов, приведена в Листинг 110.

Листинг 110. Перенаправление вызовов в реализации интерфейсной функции (SensorLib.cpp)

ErrorCode readSensorValues(SensorValueCallback callback, void* pContextData)

{

ErrorCode error = ERROR_NO;

try

{

using namespace std::placeholders;

g_SensorControl->readSensorValues(std::bind(callback,_1,_2,pContextData)); // (1)

}

catch (sensor::sensor_exception& e)

{

error = e.code();

}

return error;

}

В общем-то, вся реализация заключается в вызове метода интерфейсного класса (строка 1), в который вместо непосредственно обратного вызова передается объект связывания. Функция обратного вызова, объявленная в интерфейсе API, принимает 3 входных параметра: номер датчика, значение датчика и указатель на контекст. Когда будет происходить обратный вызов, то объект связывания вызовет назначенную функцию, в которую передаст первые два параметра исходной функции, а в третий параметр будет передан переданный указатель на контекст.

6.4. Итоги

На примере разработки модуля управления датчиками кратко описаны типовые этапы проектирования: описание технического задания; оформление сценариев функционирования системы; декомпозиция и формирование архитектуры. Затем рассмотрена реализация классов с акцентом на использовании обратных вызовов. И в заключение показан процесс создания системного API и трудности, с которыми сталкивается разработчик при реализации концепции «API как оболочка». Как можно увидеть в рассмотренном примере, в практике разработки ПО существует множество ситуаций, когда целесообразно использовать обратные вызовы как элементы дизайна компонентов системы.

Заключение

Итак, наше повествование подходит к концу, пора подвести некоторые итоги.

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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