本文分析 sigslots 是什么
QT中实现的有sigslot组件,但是不能在外部独立使用
webrtc中使用了这个独立的sigslots库
http://sigslot.sourceforge.net/.
本文试图描述一下这个sigslot组件的用法
sigslots解决什么问题
看一下官方文档中的例子
1class Switch
2{
3public:
4 virtual void Clicked() = 0;
5};
6
7class Light
8{
9public:
10 void ToggleState();
11 void TurnOn();
12 void TurnOff();
13};
在不修改Switch和Light的代码的情况下,要想让Switch对象控制Light对象
需要写一个ToggleSwitch类,实现Switch接口,把Light作为成员变量,如下
1class ToggleSwitch : public Switch
2{
3public:
4 ToggleSwitch(Light &lp)
5 {
6 m_lp = lp;
7 }
8 virtual void Clicked()
9 {
10 m_lp.ToggleState();
11 }
12
13private:
14 Light &m_lp;
15};
16
17Light lp1, lp2;
18ToggleSwitch tsw1(lp1), tsw2(lp2);
使用sigslots后的代码如下
1class Switch
2{
3public:
4 signal0<> Clicked;
5};
6class Light : public has_slots<>
7{
8public:
9 void ToggleState();
10 void TurnOn();
11 void TurnOff();
12};
13Switch sw1, sw2;
14Light lp1, lp2;
15
16sw1.Clicked.connect(&lp1, &Light::ToggleState);
17sw2.Clicked.connect(&lp2, &Light::ToggleState);
我们把signal比作插头
slot比作插座
每一个插头都可以插入一个插座的某个位置上
后续如果想添加功能也更方便,如下
1Switch sw3, sw4, all_on, all_off;
2Light lp3, lp4;
3sw3.Clicked.connect(&lp3, &Light::ToggleState);
4sw4.Clicked.connect(&lp4, &Light::ToggleState);
5
6all_on.Clicked.connect(&lp1, &Light::TurnOn());
7all_on.Clicked.connect(&lp2, &Light::TurnOn());
8all_on.Clicked.connect(&lp3, &Light::TurnOn());
9all_on.Clicked.connect(&lp4, &Light::TurnOn());
10
11all_off.Clicked.connect(&lp1, &Light::TurnOff());
12all_off.Clicked.connect(&lp2, &Light::TurnOff());
13all_off.Clicked.connect(&lp3, &Light::TurnOff());
14all_off.Clicked.connect(&lp4, &Light::TurnOff());
sigslots 信号参数
signal和slot支持多个参数
每个参数都支持自定义类型
比如
signal0<>定义了零个参数的signal
signal1<type1>定义了一个参数的signal
signal2<type1, type2>定义了二个参数的signal
比如以下例子
1class Window
2{
3public:
4 enum WindowState
5 {
6 Minimised,
7 Normal,
8 Maximised
9 };
10 signal1<WindowState> StateChanged;
11 signal2<int, int> MovedTo;
12 signal2<int, int> Resized;
13};
14
15class MyControl : public Control, public has_slots<>
16{
17public:
18 void OnStateChanged(WindowState ws);
19 void OnMovedTo(int x, int y);
20 void OnResize(int x, int y);
21};
22
23Window w;
24MyControl c;
25
26w.StateChanged.connect(&c, &MyControl::OnStateChanged);
27w.MovedTo.connect(&c, &MyControl::OnMovedTo);
28w.Resized.connect(&c, &MyControl::OnResize);
sigslots 发出信号
连接完signal和slot后
可以使用signal向slot发出信号
1// 定义信号
2signal2<char *, int> ReportError;
3
4// 发出信号,有两种方法
5
6// 方法一
7ReportError("Something went wrong", ERR_SOMETHING_WRONG);
8
9// 方法二
10ReportError.emit("Something went wrong", ERR_SOMETHING_WRONG);
sigslots强大的一点是一个信号可以同时connect多个slots
每次用上面的方法发出信号后,所有connect的slots都会收到信号
但是sigslots库目目前的实现不保证slots收到信号的顺序,也不支持优先级
sigslots实现
待补充