Обратные вызовы в C++ - [43]
6.2.2. Обработка ошибок
В процессе работы любой программы могут ситуации, приводящие к ошибкам. Причины ошибок могут быть самыми различными: неправильные действия пользователя, некорректная работа ПО, сбои в работе оборудования и т. п. Таким образом, возникает необходимость реализации подсистемы обработки ошибок, которая осуществляет восстановление работоспособности компонента после возникновения ошибочной ситуации и уведомление об этом пользователя.
В общем случае существуют две модели обработки ошибок: анализ кодов возврата и использование исключений. Несмотря на то, что использование исключений в последнее время подвергается серьезной критике, вплоть до того, что в новых языках программирования от них избавляются, в C++ указанный механизм остается востребованным, и мы также им воспользуемся. Объявления для формирования исключений представлены в Листинг 87.
>namespace sensor
>{
>enum class SensorError: uint32_t // (1)
>{
> NoError = 0,
> NotInitialized = 1,
> UnknownSensorType = 2,
> UnknownSensorNumber = 3,
> SensorIsNotOperable = 4,
> DriverIsNotSet = 5,
> InvalidArgument = 6,
> NotSupportedOperation = 7,
> InitDriverError = 8
>};
>class sensor_exception : public std::exception // (2)
>{
>public:
> sensor_exception(SensorError error);
> SensorError code() const;
> virtual const char* what() const;
> static void throw_exception(SensorError error); // (3)
>private:
> SensorError code_;
>};
>}; //namespace sensor
В строке 1 объявлены коды возможных ошибок, в строке 2 объявлен класс исключений. Если при выполнении где-то в коде возникает ошибка, то в этом месте нужно вызвать метод, объявленный в строке 3. Указанный метод выбросит исключение с соответствующим кодом.
6.2.3. Драйвер
Драйвер предназначен для взаимодействия с аппаратным обеспечением. Класс, представляющий обобщенный интерфейс для работы с драйвером, приведен в Листинг 88.
>namespace sensor
>{
>class IDriver
>{
>public:
> virtual void initialize() = 0; // (1)
> virtual void activate(SensorNumber number) = 0; // (2)
> virtual bool isOperable(SensorNumber number) = 0; // (3)
> virtual SensorValue readSpot(SensorNumber number) = 0; // (4)
> virtual SensorValue readSmooth(SensorNumber number) = 0; // (5)
> virtual SensorValue readDerivative(SensorNumber number) = 0; // (6)
> virtual ~IDriver() = default;
> static DriverPointer createDriver(DriverType type); // (7)
>};
>}; //namespace sensor
В строке 1 объявлен метод для инициализации драйвера. В строке 2 объявлен метод для активации датчика. В строке 3 объявлен метод, возвращающий признак работоспособности датчика. В строках 4, 5 и 6 объявлены методы для чтения соответственно текущих, сглаженных и производных значений. Метод в строке 7 представляет собой фабрику классов, в котором происходит создание класса соответствующего типа.
От общего интерфейса наследуются классы, реализующие драйверы различных типов. В нашей системе реализованы три типа драйверов: драйвер для работы с шиной USB; драйвер для работы через сеть Ethernet; имитируемый драйвер. Диаграмма классов изображена на Рис. 28.
Рис. 28. Диаграмма классов, реализующих драйверы
Драйверы для работы с физическими устройствами формируют команды, посылают их через соответствующие протоколы и возвращают результаты. Реализацию этих драйверов мы рассматривать не будем, поскольку работа с hardware – это отдельная тема, для изучения которой требуется не одна книга. Для нас представляет интерес реализация имитируемого драйвера.
Очевидно, что имитируемый драйвер должен возвращать заранее заданные значения. Самое простое решение, лежащее на поверхности, заключается в том, чтобы хранить эти значения в глобальных или статических переменных и возвращать их в соответствующих методах. Однако в этом случае имитация будет очень примитивной: для всех датчиков будет возвращаться одно и то же значение. Можно хранить свое возвращаемое значение в каждом классе датчика, что больше похоже на работу в реальной системе, но это также не лишено недостатков: мы не можем моделировать изменения показателей в динамике. Лучшим решением было бы предоставить возможность пользователю возвратить значение в момент запроса, для чего нам, конечно же, понадобится обратный вызов. Обратный вызов будет использоваться по схеме «Запрос данных» (см. п. 1.2.1).
Итак, для реализации интерфейса имитируемого драйвера нам понадобятся дополнительные методы и определения (см. Листинг 89).
>class DriverSimulation : public IDriver
>{
>public:
> enum ReadType { READ_SPOT = 0, READ_SMOOTH = 1, READ_DERIVATIVE = 2 }; // (1)
> using OnReadValue = std::function
> using OnOperable = std::function
> void initialize() override;
> void activate(SensorNumber number) override;
> bool isOperable(SensorNumber number) override;
> void setDefaultValue(SensorValue value); // (4)
> void setDefaultOperable(bool isOperable); // (5)
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.