Обратные вызовы в C++ | страница 94
В строке 15 назначается отслеживание пороговых значений, в строке 16 отслеживание выключается. С помощью метода, объявленного в строке 17, можно создать экземпляр соответствующего интерфейсного класса.
Класс, реализующий интерфейс, приведен в Листинг 98.
>namespace sensor
>{
>class ISensor;
>class IDriver;
>class CommandQueue;
>class AlertControl;
>class SensorContainer;
>class SensorControl: public ISensorControl
>{
> public:
> SensorControl();
> ~SensorControl();
> void initialize() override;
> /* Other Interface methods – they are not displayed here*/
> private:
> SensorContainer* sensorContainer_; // (1)
> CommandQueue* commandQueue_; // (2)
> AlertControl* alertControl_; // (3)
> bool isInitialized_; // (4)
> DriverPointer driver_; // (5)
> void checkInitialize(); // (6)
> void checkDriver(); // (7)
>};
>}; //namespace sensor
В строке 1 объявлен контейнер для хранения датчиков, в строке 2 – класс для выполнения асинхронных запросов, в строке 3 – класс для отслеживания пороговых значений. Соответствующие указатели создаются в конструкторе и уничтожаются в деструкторе. Индикатор 4 указывает, была ли выполнена инициализация.
В строке 6 объявлен вспомогательный метод, который проверяет, была ли выполнена инициализация (если нет, выбрасывает исключение). В строке 7 аналогичный метод проверяет, был ли установлен драйвер.
Рассмотрим, как здесь используются обратные вызовы. Для начала самый простой случай – чтение показаний работоспособных датчиков (Листинг 99).
>void SensorControl::readSensorValues(SensorValueCallback callback)
>{
> checkInitialize(); // (1)
> sensorContainer_->forEachSensor([callback](SensorNumber number, SensorPointer sensor) // (2)
> {
> if (sensor->isOperable()) // (3)
> {
> callback(number, sensor->getValue()); // (4)
> }
> }
> );
>}
В строке 1 производится проверка, инициализирован ли класс. Если класс не проинициализирован, то функция выбросит исключение.
В строке 2 происходит перебор элементов контейнера, в качестве обратного вызова используется лямбда-выражение. Контейнер будет вызывать лямбда-выражение, в которое он будет передавать номер датчика и указатель на экземпляр класса. В теле выражения проверяется, является ли датчик работоспособным (строка 3), и если да, то выполняется соответствующий обратный вызов (строка 4).