Иногда разработчику на С++ нужно остановиться и трезво оценить выполняемую задачу, оценить глубину своих знаний, оценить возможности STL и различных других библиотек, оценить сложность реализации элементарных парадигм средствами языка C++, и, осознав предстоящие трудности, перенести свой код в C#, например, или другой подходящий современный язык. Не будьте консерваторами!
В устоявшуюся терминологию программистов C++ входят понятие раннего связывания (на стадии компиляции) и понятие позднего, отложенного связывания (динамически, во время исполнения). Далее в статье будет предложено решение для не просто позднего, а по-настоящему запоздалого связывания данных. Представьте, что Вы можете выбирать обработчик для данных прямо во время выполнения программы и, более того, ассоциировать с данными несколько обработчиков. Представьте, что при этом работает полиморфизм. Представьте, что если Вам более не нужны выдаваемые объектом данные, Вы можете "отключиться" от объекта, как клиент от сервера. Как такое реализовать? Читать далее...Со времен C известна методика использования указателей на функции. Это так называемый "косвенный вызов", используемый для организации callback-функций. В C++ на смену косвенным вызовам пришел объектно-ориентированный подход, но, что важно, косвенные вызовы все так же доступны для использования. Что они могут дать в C++? Прежде всего, некоторое нарушение инкапсуляции для классов, которое в малых дозах может оказаться полезным. Если условно назвать иерархию классов при наследовании "вертикальной", то использование косвенных вызовов позволяет получить "горизонтальную" иерархию. Для организации позднего связывания задействованы два класса — Signal и Wire. Класс Signal используется как базовый для создания классов-сигналов. Класс-сигнал является связующим звеном между отправителем и получателем данных. Сигнал может генерироваться где угодно, и получат его все подключенные к сигналу клиенты. Класс Wire используется для увязывания сигнала с клиентом-получателем (метод Connect()), и для генерации сигнала из требуемого места программы (метод Callback()). Для удобства использования основные вызовы объявлены через макросы. Макрос DECLARE_SIGNAL объявляет новый класс-сигнал. Это объявление может быть сделано как в глобальном пространстве имен, так и внутри класса. Макросы CONNECT_SIGNAL и DISCONNECT_SIGNAL устанавливают или разрывают связь с клиентом; в качестве клиента выступает метод класса. Макрос CALLBACK эмитирует класс-сигнал.