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

void SensorControclass="underline" :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).

Рассмотрим теперь поиск максимального и минимального значения для заданного диапазона номеров датчиков. Вначале разработаем вспомогательный класс, который будет последовательно принимать на вход показания датчиков и искать среди них максимальное и минимальное значение (Листинг 100).

Листинг 100. Класс для анализа минимального и максимального значения (SensorControl.cpp)

class FindMinMaxValue

{

public:

  enum MinMaxSign { MIN_VALUE = 0, MAX_VALUE = 1 };  // (1)

  FindMinMaxValue(SensorNumber first, SensorNumber last, MinMaxSign sign) :  // (2)

    sign_(sign), first_(first), last_(last), count_(0)

  {

    if (sign == MIN_VALUE)

    {

      result_ = std::numeric_limits<SensorValue>::max();  // (3)

    }

    else

    {

      result_ = std::numeric_limits<SensorValue>::min();  // (4)

    }

    arrayFunMinMax_[MIN_VALUE] = &FindMinMaxValue::CompareMin;  // (5)

    arrayFunMinMax_[MAX_VALUE] = &FindMinMaxValue::CompareMax;  // (6)

  }

  void operator()(SensorNumber number, SensorPointer sensor)                  // (7)

  {

    if ( sensor->isOperable() && (number >= first_ && number <= last_) )  // (8)

    {

        (this->*arrayFunMinMax_[sign_])(sensor->getValue());              // (9)

        count_++;                                                         // (10)

    }

  }

  SensorValue result() { return result_; }  // (11)

  size_t count() { return count_; }         // (12)

private:

  SensorNumber first; // (13)

  SensorNumber last;  // (14)

  MinMaxSign sign;    // (15)

  SensorValue result; // (16)

  size_t count;       // (17)

  using FunMinMax = void (FindMinMaxValue::*)(SensorValue value);  // (18)

  void CompareMin(SensorValue value)  // (19)

  {

      if (result_ > value)

      {

          result_ = value;

      }

  }

  void CompareMax(SensorValue value)  // (20)

  {

    if (result_ < value)

    {

      result_ = value;

    }

  }

  FunMinMax arrayFunMinMax_[2];       // (21)

};

В строке 2 объявлен конструктор, который принимает на вход следующие параметры: минимальное значение диапазона номеров; максимальное значение диапазона номеров; параметр, указывающий, что необходим поиск минимального либо максимального значения. В конструкторе инициализируются переменные класса: минимальное значение диапазона (объявлено в строке 13); максимальное значение диапазона (объявлено в 14); параметр для поиска (объявлено в 15); итоговый результат (объявлено в 16); количество датчиков, которые участвовали в поиске (объявлено в 17). В зависимости от переданного параметра начальный результат инициализируется соответственно максимальным либо минимальным значением (строки 3 и 4). Кроме того, инициализируется массив указателей на функцию (строки 5 и 6, объявление в 21). Данные функции предназначены для сравнения и запоминания максимального либо минимального значений (объявлены в 19 и 20).

Анализ очередного значения происходит в перегруженном операторе 7. На вход подаются номер датчика и указатель на датчик. Если датчик работоспособный и его номер попадает в заданный диапазон номеров (строка 8), то в зависимости от параметра поиска через указатель вызывается соответствующая функция для анализа (строка 9), а также увеличивается счетчик просмотренных датчиков (строка 10). Функции 11 и 12 возвращают итоговые результаты.

Итак, класс для анализа готов. Теперь можно вызвать метод для итерации по элементам контейнера, и в качестве обратного вызова передать экземпляр соответствующего вспомогательного класса. Метод будет вызывать перегруженный оператор, и таким образом, мы узнаем минимальное либо максимальное значение (Листинг 101).