signal/slot机制分析

最近在看google talk的libjingle模块,里面大量使用了signal/slot机制,下面就这个机制说明下自己的理解。

 

所谓signal,即信号;

所谓slot,即信号触发后所要处理的事情(所要调用的函数)。

之所以称其为slot(槽),我这么理解:当一个signal被触发后,有可能处理多个事件(函数),将signal想象为一张表(信号-处理函数),那么每个处理函数便是表中的一个槽。

 

我们基于一个简单的场景来分析这个机制:

有一个对话框,上面有两个按钮(称b1与b2),并有一个文本标签(称label),欲实现如下功能:

1、点击b1,lable显示“点击了b1”

2、点击b2, lable显示“点击了b2”

 

b1的类的定义如下

class cb1
{
public:
    void on_b1_click();
    signal0<> Click;               // signal对象
}

 

b2的类的定义如下

class cb2
{
public:
    void on_b2_click();
    signal0<> Click;               // signal对象
}

 

对话框类定义如下

class dlg
{
void set_from_b1() { edit.setwindowtext(“点击了b1”)}
void set_from_b2() { edit.setwindowtext(“点击了b2”)}
}

 

在对话框的初始化函数内,有如下调用

b1.Click.connect(this, set_from_b1);            // 将set_from_b1函数注册给b1.Click信号
b2.Click.connect(this, set_from_b2);            // 将set_from_b2函数注册给b2.Click信号

 

b1被按下时的响应函数

void cb1::on_b1_click()
{
    // 执行其对应的信号处理函数
    // 在本例中,为set_from_b1
    Click.emit();
}

 

b2被按下时的响应函数

void cb2:on_b2_click()
{
    // 执行其对应的信号处理函数
    // 在本例中,为set_from_b2
    Click.emit();
}

通过以上的伪代码,我们实现了这两个功能,并且,class cb1,cb2完全独立,可实现复用。

 

代码分析:

以上代码的关键之处在于两个地方:

1、事件处理函数的注册

观察class signal0的内部实现,原理是,将参数传入的类对象指针与其函数指针,打包存入一个容器。待后续调用。

2、事件处理函数的执行

注册后,当执行emit时,遍历signal0对象内部的容器,取出函数指针一一调用即可。

posted @ 2011-09-30 17:16  沈星星  阅读(1921)  评论(0编辑  收藏  举报