Обратные вызовы в C++ | страница 94



В строке 15 назначается отслеживание пороговых значений, в строке 16 отслеживание выключается. С помощью метода, объявленного в строке 17, можно создать экземпляр соответствующего интерфейсного класса.


Класс, реализующий интерфейс, приведен в Листинг 98.

Листинг 98 Класс, реализующий интерфейс (SensorControl.h)

>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).

Листинг 99. Обратные вызовы в классе, реализующем интерфейс (SensorControl.cpp)

>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).