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的函数都别调用了。这不就是传说中的“杀人”于无形中,这样很大程度上封装了函数,简化了表现层的复杂度。

  • 相关阅读:
    B站崩溃的背后,b站高可用架构到底是怎么样的?
    批量查询注册表键值函数 RegQueryMultipleValues 应用一例
    windows服务程序的安装和卸载函数
    API 获得GetLastError()错误代码对应的文字信息
    API 在屏幕上简单显示字符串
    API 实现类似于 C# DateTime 的类
    Windows API ReportEvent 写系统日志
    .net core 新增对DOCKER后报 ERR_EMPTY_RESPONSE
    Windows docker 安装报 WSL 2 installation is incomplete.
    SSD固态硬盘装系统无法进入引导
  • 原文地址:https://www.cnblogs.com/fengju/p/6174340.html
Copyright © 2011-2022 走看看