signal-slot 信号槽技术初探一

信号槽技术由来已久, 早就听说在QT中大量应用,一起未曾研究, 最近要用到 libjingle, 看了相关文章和代码。

它利用了模板技术将 消息producer--触发信号的那个对象 和 consumer -- 接受信号的那个对象(槽) 进行解耦, 很好的简化了代码.

类似的技术常用的是 callback,  如典型的event and dispatch loop, onEvent, onConnect 等回调方式。

当设定的信号产生时, producer 对象调用 consumer对象的回调方法, 在实现上显然不如信号槽灵活


不说废话,让代码说话


一般的写法

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include "sigslot.h"

using namespace std;
using namespace sigslot;

//example 0

class CSwitch
{
public:
    virtual void Clicked() = 0;

};

class CLight
{
public:
    CLight():state(false) {}
    void ToggleState() {
        state = !state; 
    } 
    void TurnOn()  { state=true; };
    void TurnOff() { state=false; };
    void printState() { 
        if(state) printf("on\n");
        else printf("off\n");
    }

private:
    bool state;
};


class ToggleSwitch : public CSwitch
{
public:
    ToggleSwitch(CLight& lp):m_lp(lp)
    {}
    virtual void Clicked()
    {
        m_lp.ToggleState();
    }
private:
    CLight& m_lp;
};

#ifdef __TEST_SIGSLOT__
int main(int argc, char* argv[])
#else
int sigslot_usage(int argc, char* argv[])
#endif
{
    //example 1
    CLight lp1, lp2;
    CSwitch* pSw1 = new ToggleSwitch(lp1);
    CSwitch* pSw2 = new ToggleSwitch(lp2);

    lp1.printState();
    pSw1->Clicked();
    lp1.printState();
    
    lp2.printState();
    pSw2->Clicked();
    lp2.printState();

    delete pSw1;
    delete pSw2;
    return 0;
}


--- output---

off
on
off
on


用信号槽的写法如下,这其中用到的sigslot.h 来自 http://sigslot.sourceforge.net/ , 很好用的信号槽库,就一个头文件

例一

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include "sigslot.h"

using namespace std;
using namespace sigslot;

//example 1

class Switch
{
public:
	void execute() {Clicked();}
	signal0<> Clicked;
};


class Light : public has_slots<>
{
public:
    Light():state(false) {}
	void ToggleState() {
		state = !state; 
	} 
	void TurnOn()  { state=true; };
	void TurnOff() { state=false; };
	void printState() { 
		if(state) printf("on\n");
		else printf("off\n");
	}

	
private:
	bool state;
};

#ifdef __TEST_SIGSLOT1__
int main(int argc, char* argv[])
#else
int sigslot_usage1(int argc, char* argv[])
#endif
{
    //example 1
	Switch sw1, sw2;
	Light lp1, lp2;

	sw1.Clicked.connect(&lp1, &Light::ToggleState);
	sw2.Clicked.connect(&lp2, &Light::ToggleState);

	lp1.printState();
	sw1.execute();
	lp1.printState();
	
	lp2.printState();
	sw2.execute();
	lp2.printState();

	return 0;
}

--- Output ---

off
on
off
on


例二

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include "sigslot.h"

using namespace std;
using namespace sigslot;

//example 2
class Sender {
public:
	sigslot::signal2<string, std::time_t> SignalDanger;


    void Panic(){
	    SignalDanger("Help!", std::time(0)); 
	}						 
};

class Receiver : public sigslot::has_slots<> {
public:	
	Receiver(Sender& sender) { 
		sender.SignalDanger.connect(this, &Receiver::OnDanger);
	}

	void OnDanger(string message, std::time_t time) {
	    if(message == "Help!") cout<<"help when "<<time<<endl;

	}

};

#ifdef __TEST_SIGSLOT2__
int main(int argc, char* argv[])
#else
int sigslot_usage2(int argc, char* argv[])
#endif
{
	Sender sender;
	Receiver receiver(sender);
	sender.Panic();


	return 0;
}


--- Output ---

help when 1350872883


以上代码根据其官方文档整理, 接下来要看下信号槽的内部实现机制

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值