Центр уведомлений на С++

После некоторого времени программирования с платформами iOS и Mac Objective C я полюбил общий шаблон уведомлений, реализованный классами NSNotificationCenter и NSNotification. Возвращаясь к C++, который всегда был моим языком выбора для большинства вещей, я поймал себя на том, что пытаюсь воспроизвести этот шаблон и считаю, что на самом деле уже должна быть универсальная реализация подобных классов C++, предлагающая его поддержку.

Кажется, что шаблон несколько сложнее реализовать на C++, чем на Objective C, из-за более динамичного характера последнего, но это не кажется невозможным. Я просмотрел библиотеки наддува, поскольку они, как правило, потрясающие, и мне было грустно, что мне не повезло. Хотя кажется, что boost::bind, boost::lamda, boost::function делают большую часть работы. Я пропустил что-то очевидное? Есть ли что-то уже существующее, что позволило бы мне легко воспроизвести поведение NSNotification/NSNotificationCenter?


person jbat100    schedule 04.11.2011    source источник
comment
Вы пробовали Boost.signals?   -  person anno    schedule 05.11.2011
comment
Я посмотрю, спасибо за предложение.   -  person jbat100    schedule 05.11.2011
comment
Используя несколько иной подход, Qt реализовал сигналы и слоты с помощью специального инструмента предварительной обработки (компилятор метаобъектов moc ‹-›). Однако разумно использовать его только в том случае, если qt ui соответствует вашим потребностям.   -  person Pascal T.    schedule 05.11.2011


Ответы (3)


Теоретически вы можете создать класс с вектором указателей на функции для вызова при вызове определенного уведомления. Класс со словарем, в котором объекты являются векторами функций для вызова при отправке уведомления.

person DanZimm    schedule 05.11.2011

В дополнение к пакетам boost, упомянутым в других ответах, другим вариантом является poco::NotificationCenter.

Эта реализация ближе к структуре уведомлений Cocoa, что конкретно обсуждалось в документации Poco:

Класс NotificationCenter в основном является реализацией C++ класса NSNotificationCenter, найденного в Apple Cocoa (или OpenStep).

person Ricardo Sanchez-Saez    schedule 06.02.2015

Следуя рекомендации @anno взглянуть на boot::signal, после изучения он кажется возможным вариантом, хотя, как и ожидалось, он не так прост, как объективные решения C. Просматривая руководство по boost::signal, я думал, что пройдусь по наиболее важным аспектам проблемы.


Чтобы создать отправителей уведомлений:

Рассмотрим простую службу доставки новостей, где клиенты подключаются к поставщику новостей, который затем отправляет новости всем подключенным клиентам по мере поступления информации. Служба доставки новостей может быть построена следующим образом:

class NewsItem { /* ... */ };
boost::signal<void (const NewsItem&)> deliverNews;

Целью deliverNews является информирование наблюдателей о том, что NewsItem был сгенерирован.


Наблюдателей можно добавить следующим образом (используя библиотеку boost::bind):

Клиентам, которые хотят получать обновления новостей, нужно только подключить функциональный объект, который может получать новости, к сигналу DeliverNews. Например, у нас может быть специальная область сообщений в нашем приложении специально для новостей, например:

struct NewsMessageArea : public MessageArea
{
public:
  // ...

  void displayNews(const NewsItem& news) const
  {
    messageText = news.text();
    update();
  }
};

// ...
NewsMessageArea newsMessageArea = new NewsMessageArea(/* ... */);
// ...
deliverNews.connect(boost::bind(&NewsMessageArea::displayNews, newsMessageArea, _1));

Чтобы решить проблему удаления наблюдателей, которые были освобождены из списка, boost::signal предлагает следующее решение.

Однако что, если пользователь закроет область сообщения новостей, уничтожив объект newsMessageArea, о котором знает deliveryNews? Скорее всего, произойдет ошибка сегментации. Однако с Boost.Signals нужно только сделать NewsMessageArea отслеживаемым, и слот, связанный с newsMessageArea, будет отключен при уничтожении newsMessageArea. Класс NewsMessageArea становится отслеживаемым путем публичного унаследования от класса boost::signals::trackable, например:

struct NewsMessageArea : public MessageArea, public boost::signals::trackable
{
  // ...
};

В настоящее время существует существенное ограничение на использование отслеживаемых объектов при создании слотовых соединений: объекты-функции, созданные с использованием Boost.Bind, понимаются таким образом, что указатели или ссылки на отслеживаемые объекты, переданные в boost::bind, будут найдены и отслежены.

person jbat100    schedule 05.11.2011