Авторизация
.
Контакты
.
Предложения
.
Начало
.
Обратные вызовы в C++
· · ·
· · ·
1. Теоретические основы обратных вызовов.
1.1. Концепция обратных вызовов.
1.1.1. Интуитивное определение.
1.1.2. Обратный вызов как паттерн.
1.1.3. Прямые и обратные вызовы.
1.2. Задачи, решаемые с помощью обратных вызовов.
1.2.1. Запрос данных.
1.2.2. Вычисления по запросу.
1.2.3. Перебор элементов.
1.2.4. Уведомление о событиях.
1.3. Модель обратных вызовов.
1.3.1. Определения и термины.
1.3.2. Контекст.
1.4. Архитектурный дизайн вызовов.
1.4.1. Синхронные и асинхронные вызовы.
1.4.2. Использование вызовов в API.
1.5. Итоги.
2. Реализация обратных вызовов.
2.1. Указатель на функцию.
2.1.1. Концепция.
2.1.2. Инициатор.
Листинг 1.Иинициатор с указателем на функцию.
Листинг 2. Инициатор с указателем на функцию в объектно-ориентированном дизайне.
2.1.3. Исполнитель.
Листинг 3. Исполнитель для инициатора в процедурном дизайне.
Листинг 4. Исполнитель для инициатора в объектно-ориентированном дизайне.
2.1.4. Синхронный вызов.
Листинг 5. Инициатор для синхронного обратного вызова с указателем на функцию.
2.1.5. Преимущества и недостатки.
2.2. Указатель на статический метод класса.
2.2.1. Концепция.
2.2.2. Инициатор.
Листинг 6. Инициатор с указателем на статический метод класса.
2.2.3. Исполнитель.
Листинг 7. Исполнитель с указателем на статический метод класса.
Листинг 8. Исполнитель с указателем на статический метод класса для инициатора с нетипизированным контекстом.
2.2.4. Синхронный вызов.
Листинг 9. Инициатор для синхронного обратного вызова с указателем на статический метод класса.
2.2.5. Преимущества и недостатки.
2.3. Указатель на метод-член класса.
2.3.1. Концепция.
2.3.2. Инициатор.
Листинг 10. Инициатор с указателем на метод-член класса.
2.3.3. Исполнитель.
Листинг 11. Исполнитель с указателем на метод-член класса.
2.3.4. Управление контекстом.
Листинг 12. Классы-исполнители с наследованием.
Листинг 13. Настройка указателей на классы и методы.
2.3.5. Синхронный вызов.
Листинг 14. Инициатор для синхронного обратного вызова с указателем на метод-член класса.
2.3.6. Преимущества и недостатки.
2.4. Функциональный объект.
2.4.1. Концепция.
2.4.2. Инициатор.
Листинг 15.Объявление функционального объекта.
Листинг 16. Инициатор с функциональным объектом.
2.4.3. Исполнитель.
Листинг 17. Исполнитель с функциональным объектом.
2.4.4. Синхронный вызов.
Листинг 18. Инициатор для синхронного вызова с функциональным объектом.
2.4.5. Преимущества и недостатки.
2.4.6. Производительность.
Листинг 19. Маленькая простая программа.
Листинг 20. Дизассемблерный код с выключенной оптимизацией:
Листинг 21. Дизассемблерный код с включенной оптимизацией.
2.5. Лямбда-выражение.
2.5.1. Концепция.
2.5.2. Инициатор.
2.5.3. Исполнитель.
2.5.4. Синхронный вызов.
2.5.5. Преимущества и недостатки.
Листинг 22. Лямбда-выражение с захватом указателя this.
2.6. Итоги.
3. Сравнительный анализ реализаций.
3.1. Методологические подходы.
3.1.1. Обобщенный алгоритм.
3.1.2. Требования как критерии.
3.2. Качественный анализ.
3.2.1. Матрица соответствия.
3.2.2. Выбор реализации.
3.3. Метод интегральных оценок.
3.3.1. Количественные оценки.
3.3.2. Коэффициенты важности.
3.3.3. Учет прогнозных показателей.
3.4. Итоги.
4. Обратные вызовы и шаблоны.
4.1. Общие понятия шаблонов.
Листинг 23. Объявление шаблона и его инстанциирование.
4.2. Синхронные вызовы.
4.2.1. Инициатор.
Листинг 24. Реализации инициатора для синхронных вызовов.
Листинг 25. Шаблон для инициатора синхронного вызова.
Листинг 26. Шаблон для инициатора с двумя параметрами.
4.2.2. Преобразование вызовов.
Листинг 27. Функциональный объект для вызова функции с передачей контекста.
Листинг 28. Функциональный объект для вызова метода класса.
4.2.3. Исполнитель.
Листинг 29. Исполнитель для шаблона-инициатора синхронного вызова.
Листинг 30. Преобразование вызовов без объявления промежуточных Типов.
4.3. Вызовы в алгоритмах.
4.3.1. Описание проблемы.
4.3.2. Параметризация типов.
Листинг 31. Сортировка массива методом пузырька.
Листинг 32. Параметризация типов для сортировки пузырьком.
4.3.3. Объявление предикатов.
Листинг 33. Шаблон с объявлением предиката.
Листинг 34. Сортировка данных с использованием предикатов различных типов.
4.3.4. Предикаты по умолчанию.
Листинг 35. Шаблон с предикатом по умолчанию.
4.4. Асинхронные вызовы.
4.4.1. Инициатор.
Листинг 36. Реализации инициатора асинхронных вызовов для различных типов аргументов.
Листинг 37. Шаблон для инициатора асинхронного вызова.
4.4.2. Хранение лямбда-выражений.
Листинг 38. Лямбда-выражение и объект-замыкание.
Листинг 39. Объект-замыкание с преобразованием в указатель на функцию.
Листинг 40. Сохранение лямбда-выражения в локальной переменной.
Листинг 41. Инициатор с дополнительными конструкторами.
Листинг 42.Инстанциирование шаблона асинхронного обратного вызова для лямбда-выражения.
4.4.3. Исполнитель.
Листинг 43. Исполнитель для шаблона-инициатора с различными типами аргумента.
Листинг 44. Компактный способ объявлений при использовании преобразования вызовов.
4.5. Универсальный аргумент.
4.5.1. Динамический полиморфизм.
Листинг 45. Класс, реализующий стирание типов.
Листинг 46. Использование универсального аргумента.
4.5.2. Настройка сигнатуры.
Листинг 47. Настройка сигнатуры.
Листинг 48. Стирание типов с настройкой сигнатуры.
Листинг 49. Использование аргумента с настройкой сигнатуры.
4.5.3. Вызов метода класса.
Листинг 50. Использование универсального аргумента для вызова метода класса.
4.6. Использование стандартной библиотеки.
4.6.1. Организация вызовов.
Листинг 51. Использование std::function.
Листинг 52. Проверка настройки аргумента.
4.6.2. Инициатор с универсальным аргументом.
Листинг 53. Инициатор с оболочкой std::function.
4.6.3. Преобразование с настройкой сигнатуры.
Листинг 54. Преобразование вызовов с настройкой сигнатуры для указателей на функцию.
Листинг 55. Преобразование вызовов с настройкой сигнатуры для указателей на метод класса.
4.6.4. Исполнитель.
Листинг 56. Исполнитель для инициатора с оболочкой std::function.
4.6.5. Инициатор для методов класса.
Листинг 57. Инициатор с оболочкой std::function для вызова методов класса.
Листинг 58. Использование специализации шаблона-инициатора для вызова методов класса.
Листинг 59. Использование инициатора с оболочкой std::function для вызова методов класса.
4.6.6. Перенаправление вызовов.
Листинг 60. Перенаправление вызовов.
Листинг 61. Перенаправление вызовов для методов-членов класса.
Листинг 62. Перенаправление вызовов в исполнителе.
4.6.7. Универсальный аргумент и производительность.
4.7. Проблемы, порождаемые шаблонами.
4.7.1. Недостатки шаблонов.
4.7.2. Ограничения шаблонов.
4.8. Итоги.
5. Распределение вызовов.
5.1. Постановка задачи.
5.2. Статический набор получателей.
5.2.1. Распределение в статическом наборе.
Листинг 63. Распределяющая функция для статического набора получателей.
Листинг 64. Распределение вызова для статического набора.
5.2.2. Передача данных.
Листинг 65. Распределяющая функция для статического набора получателей с передачей данных.
Листинг 66. Распределение вызовов для статического набора получателей.
5.3. Настройка сигнатуры для передачи данных.
5.3.1. Общая концепция.
Листинг 67. Пример шаблона функции с несколькими пакетами параметров.
5.3.2. Способ 1: объекты в пакет, данные в кортеж.
Листинг 68. Распределение при упаковке объектов в пакет и данных в кортеж.
5.3.3. Способ 2: объекты в кортеж, данные в пакет.
Листинг 69. Распределение при упаковке объектов в кортеж и данных в пакет.
5.3.4. Способ 3: объекты и данные в кортежах.
Листинг 70. Распределение при упаковке объектов и данных в кортежи.
5.3.5. Сравнение способов.
Листинг 71. Распределение вызовов с заданной сигнатурой.
5.3.6. Настройка сигнатуры для перенаправления.
Листинг 72. Перенаправление вызовов с настройкой сигнатуры.
5.4. Возврат результатов выполнения.
5.4.1. Получение возвращаемых значений.
Листинг 73. Распределение вызовов с возвратом результатов.
5.4.2. Анализ результатов.
Листинг 74. Анализ возвращаемых значений.
5.5. Распределитель для статического набора.
5.5.1. Распределение без возврата результатов.
Листинг 75. Распределитель для статического набора получателей.
Листинг 76. Использование распределителя для статического набора.
5.5.2. Распределение с возвратом результатов.
Листинг 77. Распределитель для статического набора с возвратом результатов.
Листинг 78. Использование распределителя для статического набора с возвратом результатов.
5.5.3. Параметризация возвращаемого значения.
Листинг 79. Условная компиляция в зависимости от типа возвращаемого значения.
Листинг 80. Условная компиляция в зависимости от типа возвращаемого значения.
5.6. Динамический набор получателей.
5.6.1. Распределение в динамическом наборе.
Листинг 81. Распределитель для динамического набора получателей.
5.6.2. Получение возвращаемых значений.
Листинг 82. Возврат значений для динамического набора получателей.
Листинг 83. Распределение вызовов для динамического набора получателей.
5.7. Адресное распределение.
5.7.1. Понятие адресного распределения.
5.7.2. Адресный распределитель.
Листинг 84. Распределитель для адресного набора получателей.
5.7.3. Использование адресного распределения.
Листинг 85. Использование адресного распределения.
5.8. Итоги.
6. Практическое использование обратных вызовов.
6.1. Разработка архитектуры.
6.1.1. Техническое задание.
6.1.2. Сценарий функционирования.
6.1.3. Декомпозиция системы.
6.2. Реализация классов.
6.2.1. Общие определения.
Листинг 86. Общие объявления типов (SensorDef.h).
6.2.2. Обработка ошибок.
Листинг 87. Исключения для обработки ошибок (Errors.h).
6.2.3. Драйвер.
Листинг 88. Интерфейс для работы с драйвером (DriverInterface.h).
Листинг 89. Имитируемый драйвер (DriverImpl.h).
Листинг 90. Чтение текущего значения датчика в имитируемом драйвере (DriverImpl.cpp).
6.2.4. Датчик.
Листинг 91. Интерфейсный класс для роботы с датчиком (SensorInterface.h).
6.2.5. Контейнер.
Листинг 92. Объявление контейнера (SensorContainer.h).
6.2.6. Асинхронные запросы.
Листинг 93. Класс для выполнения асинхронных вызовов (CommandQueue.h).
Листинг 94. Обработка очереди запросов (CommandQueue.cpp).
6.2.7. Наблюдатель.
Листинг 95. Наблюдатель – класс для отслеживания пороговых значений (Observer.h).
Листинг 96. Отслеживание пороговых значений.
6.2.8. Интерфейсный класс.
Листинг 97. Интерфейсный класс (ControlInterface.h).
Листинг 98 Класс, реализующий интерфейс (SensorControl.h).
Листинг 99. Обратные вызовы в классе, реализующем интерфейс (SensorControl.cpp).
Листинг 100. Класс для анализа минимального и максимального значения (SensorControl.cpp).
Листинг 101. Поиск минимального и максимального значений (SensorControl.cpp).
6.3. Разработка системного API.
6.3.1. API как оболочка.
Листинг 102. Концептуальный пример реализации API как оболочки.
6.3.2. Объявления типов.
Листинг 103. Объявления типов для интерфейса API (SensorLib.h).
6.3.3. Интерфейс API и обработка ошибок.
Листинг 104. Интерфейс системного API (SensorLib.h).
Листинг 105. Функция для получения значения датчика.
6.3.4. Многопоточная работа.
Листинг 106. Объявление экземпляра класса как локального для текущего выполняемого потока (SensorLib.cpp).
6.3.5. Настройка драйвера.
Листинг 107. Настройка драйвера в исходной реализации.
Листинг 108. Настройка драйвера в системном API (SensorLib.h).
Листинг 109. Конвертер числовых значений в перечисление (EnumConverter.h).
6.3.6. Обратные вызовы.
Листинг 110. Перенаправление вызовов в реализации интерфейсной функции (SensorLib.cpp).
6.4. Итоги.
Заключение.
Список литературы и интернет-источников.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.