理论
- 当对象的内部状态以某种可能使对象的客户端或者所有感兴趣的方式改变时,该对象就会发出信号。
- 发出信号后,与其连接的插槽通常会立即执行,就像正常的函数调用一样。
槽:Slot
文件:cyber/base/signal.h
从这个类可以学到变参是怎么写的
有两个成员变量
数据类型 | 变量名 | 说明 |
---|---|---|
Callback | cb_; | 函数指针,在构造函数中指令 |
bool | connected_ = true; | 在构造函数中指定,槽有一个开关,决定信号是否可以连接到这里 |
关键函数:关键自傲与重写了operator(),如果满足要求,那么调用了Slot(…)之后就会自动调用构造函数中注册的回调函数
除此之外,还可以看下它的构造是怎么样的:
另外,还提供了两个操作函数:
可以在cyber/base/signal_test.cc中学到这个类应该怎么用:
小结:它其实就保存了一个回调函数std::function<void(Args…)> cb_和一个标记bool connected_,提供一个Disconnect函数用来将标记置为false。它也和信号一样重载了()操作符,当被调用时就会去运行cb_函数。
信号:Signal
我们先来看下它是怎么用的。
首先,一个信号可以连接多个槽函数。这从它的成员变量中也可以体现出来:
成员变量: slots记录了管理到该信号下的所有槽
Signal中的函数都是线程安全的。
operator()
然后它还重载了operator()函数,它会调用关联到这个信号对应的所有槽(所有关联的回调函数),其实就是通知所有监听该信号的回调函数
可以看到具体的动作就是slot的operator()来做的
Connect(const Callback& cb)
作用:
- 根据指定回调函数创建一个slot,然后加入到自己的关联槽列表
- 然后使用slot和signal创建了一根管子
可以看到它只是构造了一根管子
Disconnect(const ConnectionType& conn)
- 接收一个Connection参数,从槽列表中找到该槽,然后将槽的标记置为false并从列表中删除。
- 删除动作是由槽函数的Disconnect()来做的
关联:Connection
它的成员变量如下:
可以看到,connection相当于一根管子,管子两端分别是slot和signal。
成员函数
HasSlot
从上面我们可以推断出两个关键点:
- slot和slot_均不能为null,只要有一个为null或者全部为null,那么直接返回false
- HasSlot比较的是slot和slot_的地址
IsConnected()
这根管子是不是通的,由槽来决定
Disconnect
connect的断开动作是调用信号signal_的Disconnect实现的
如果signal_确实是使用了当前conn关联了slot,那么调用slot的Disconnect
这样就不会调用到slot绑定的那个回调函数了。
小结:保存了一个信号的指针一个槽的指针,一个Connection实例就代表了一条关联关系。通过Slot的标记位显示是否处于关联状态。