2.1 用 Qt 信号-槽实现消息分发

        本文是 《基于 Qt 实现消息总线》的其中一节,建议全章阅读。


        针对消息,主要有订阅、取消订阅、发布 3 种操作。基于 Qt 的信号-槽来实现,是很简单的。

class QTEVENTBUS_EXPORT QMessageBase : public QObject
{
    Q_OBJECT
signals:
    void on_message(QMessageResultPointer data);
};

        对应每种消息,都有一个消息维护对象,其基类(QMessageBase)上,有一个信号(on_message)。发布消息的时候,会触发该信号。信号参数是一个 QMessageResultPointer 的对象,保存了共享的消息内容和维护反馈结果的相关数据。

        具体的消息维护对象是泛型类,与消息类型关联,在一个总线中,每种消息维护对象只有一个实例,从而维护了发布与订阅的关联性:

template<typename T>
class QMessage : public QMessageBase
{
};

        订阅的时候,连接一下信号就可以了:

template<typename T>
template<typename F>
bool QMessage<T>::subscribe(QObject const * c, F f)
{
    QObject::connect(this, &QMessageBase::on_message, c,
                         [f](QMessageResultPointer const & e){e.invoke<T, R>(f);});
    ......
    return true;
}

        我们正是利用 Qt 信号连接来记录对该类型消息的订阅,从而简化的实现。取消订阅,实际上就是断开信号连接:

template <typename T>
bool QMessage<T>::unsubscribe(QObject const * c) 
{
    QObject::disconnect(this, &QMessageBase::on_message, c, 0);
    ......
    return true;
}

        这里我们要求提供上下文 QObject 对象,一方面是为了可以准确地取消与某个上下文相关的订阅;另一方面,也提供了订阅者处理消息的线程上下文,实现跨线程消息传递。

        当发布消息时,只需要触发信号:

template <typename T>
void QMessage<T>::publish(T const & msg)
{
    int n = receivers(SIGNAL(on_message(QMessageResultPointer)));
    if (n == 0)
        return;
    QMessageResultPointer data(msg);
    emit on_message(std::move(data));
}

        通过 receivers() 方法,可以知道当前有多少个信号连接(也就是有多少个订阅者),如果没有连接,直接返回,可以提高一下处理效率。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fighting Horse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值