程序开发基础学习四(boost::signal2 函数学习)

来源:互联网 发布:淘宝微店怎么开通 编辑:程序博客网 时间:2024/05/29 12:37

        在游戏编程中,新的策划需求总是在迭代不停。。。。。。,对于游戏程序员肯定深有感触吧,遇到这种情况咱只能小小的抱怨下,活还得干。尤其是遇到耦合到很多类的时候,要是直接实现不加抽象的话,那咱的代码就要被拆的七零八落,并且在代码维护性和程序健壮性上问题很大。前面说到的问题其实就是常听到的代码耦合,说白了就是在原有的代码上插上一段代码。而signal就能很好的解决这种问题。这样不仅可以让咱的代码优美,而且修改的时候也很方便。好的,按照惯例先模拟一下signal的实现方法。看清它的真面目,也就不用害怕了。

1、signal模拟程序

#include "stdafx.h"#include <iostream>#include "boost/bind.hpp"#include "boost/function.hpp"#include "boost/signals2.hpp"using namespace std;using namespace boost;class Buttion{public:void connect(void (*f)(int, int));void OnBtnClick();private:void (*fuc_)(int, int);};void Buttion::connect(void (*f)(int, int)){fuc_ = f;}void Buttion::OnBtnClick(){fuc_(10, 20);}void PrintCodeline(int x, int y){cout<<"x:"<<x<<",y:"<<y<<endl;}int _tmain(int argc, _TCHAR* argv[]){Buttion btn;btn.connect(&PrintCodeline);btn.OnBtnClick();getchar();return 0;}

         看见了吗?其实就是传递个函数指针,不过signal用的是template而已,并且里面还有一些保护机制。在下面的程序会提到。

2、signal函数实现

#include "stdafx.h"#include <iostream>#include "boost/bind.hpp"#include "boost/function.hpp"#include "boost/signals2.hpp"using namespace std;using namespace boost;class Buttion{typedef signals2::signal<void (int ,int)> OnClick;public:typedef OnClick::slot_type OnSlottype;signals2::connection connect(const OnSlottype& type);void OnBtnClick();private:OnClick onclick_;signals2::connection connect_;};signals2::connection Buttion::connect(const OnSlottype& type){return connect_ = onclick_.connect(type);}void Buttion::OnBtnClick(){onclick_(10, 20);}void PrintCodeline(int x, int y){cout<<"x:"<<x<<",y:"<<y<<endl;}int _tmain(int argc, _TCHAR* argv[]){Buttion btn;btn.connect(&PrintCodeline);btn.OnBtnClick();getchar();return 0;}
        重点有两个方面,一个是OnSlottype,其实就相当于上一个列子中的函数指针,在一个要问为什么要返回成员变量connect_,一个原因是通过它的返回值可以知道是否connect成功,另一个在用完之后调用disconnect方法,释放connect_变量。

3、类之间相互调用

// mercurial.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include "boost/bind.hpp"#include "boost/function.hpp"#include "boost/ref.hpp"#include "boost/shared_ptr.hpp"#include "boost/signals2.hpp"using namespace std;using namespace boost;class Document{typedef signals2::signal<void (void)> signal_t;public:Document(){}signals2::connection connect(const signal_t::slot_type &subscriper){return sig_.connect(subscriper);}void Append(const char* text){text_ += text;sig_();}string GetText(){return text_;}private:signal_t sig_;string text_;};class TextView{public:TextView(Document* doc):doc_(doc){connect_ = doc_->connect(bind(&TextView::Refresh, this));}~TextView(){connect_.disconnect();}void Refresh(){cout<<doc_->GetText()<<endl;}private:signals2::connection connect_;Document* doc_;};class HexView{public:HexView(Document* doc):doc_(doc){connect_ = doc_->connect(bind(&HexView::Refresh, this));}~HexView(){connect_.disconnect();}void Refresh(){string str = doc_->GetText();for (size_t i = 0; i < str.size(); ++i){cout<<(int)str[i];}cout<<endl;}private:Document* doc_;signals2::connection connect_;};int _tmain(int argc, char* argv[]){Document *doc = new Document();TextView text(doc);HexView hex(doc);doc->Append(argc == 2 ? argv[1] : "Hello,Word.");delete doc;getchar();return 0;}

       这个程序模仿boost给出的示例写的,要注意的是在TextView和HexView两个构造函数传递的是Document的指针,之前我自己写的时候传递的是Document的复制,但是编译不过。signal自己有不允许复制的机制。这就很强大了,本来是粗心造成的一个问题(复制的话,就不能改变传递的参数了),signal在编译的时候就能检测出问题了。有点只能的感觉了。再一个在main函数里我只申明TextView和HexView两个对象。调用下Document的一个函数,就将TextView和HexView的函数都别调用了。这不就是传说中的“杀人”于无形中,这样很大程度上封装了函数,简化了表现层的复杂度。

原创粉丝点击