遵循@anno 的建议来查看 boot::signal,经过检查,它确实是一个可能的选择,尽管正如预期的那样,它不像目标 C 解决方案那样直接。浏览boost::signal 教程,我想我会针对手头的问题了解最相关的方面。
要创建通知发件人:
考虑一个简单的新闻传递服务,其中客户端连接到新闻提供者,然后在信息到达时将新闻发送给所有连接的客户端。新闻传递服务可以这样构建:
class NewsItem { /* ... */ };
boost::signal<void (const NewsItem&)> deliverNews;
的目的deliverNews
是通知观察者 aNewsItem
已经生成。
可以按如下方式添加观察者(使用 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 提供了以下解决方案
但是,如果用户关闭新闻消息区域,破坏了 DeliverNews 知道的 newsMessageArea 对象怎么办?很可能会发生分段错误。但是,使用 Boost.Signals 只需要将 NewsMessageArea 设为可跟踪,当 newsMessageArea 被销毁时,涉及到 newsMessageArea 的 slot 将被断开。NewsMessageArea 类是通过从 boost::signals::trackable 类公开派生而来的,例如:
struct NewsMessageArea : public MessageArea, public boost::signals::trackable
{
// ...
};
此时,在进行槽连接时使用可跟踪对象有很大的限制:可以理解使用 Boost.Bind 构建的函数对象,以便找到并跟踪传递给 boost::bind 的可跟踪对象的指针或引用。