zoukankan      html  css  js  c++  java
  • 程序开发基础学习四(boost::signal2 函数学习)

            在游戏编程中,新的策划需求总是在迭代不停。。。。。。,对于游戏程序员肯定深有感触吧,遇到这种情况咱只能小小的抱怨下,活还得干。尤其是遇到耦合到很多类的时候,要是直接实现不加抽象的话,那咱的代码就要被拆的七零八落,并且在代码维护性和程序健壮性上问题很大。前面说到的问题其实就是常听到的代码耦合,说白了就是在原有的代码上插上一段代码。而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的函数都别调用了。这不就是传说中的“杀人”于无形中,这样很大程度上封装了函数,简化了表现层的复杂度。

  • 相关阅读:
    Power BI for Office 365(八)共享查询
    Power BI for Office 365(七) Power BI站点
    Power BI for Office 365(六)Power Map简介
    Power BI for Office 365(五)Power View第二部分
    Power BI for Office 365(四)Power View第一部分
    Power BI for Office 365(三)Power Pivot
    Power BI for Office 365(二)Power Query
    java 继承、重载、重写与多态
    Android 热修复方案Tinker(一) Application改造
    阿里最新热修复Sophix与QQ超级补丁和Tinker的实现与总结
  • 原文地址:https://www.cnblogs.com/fengju/p/6174340.html
Copyright © 2011-2022 走看看