boost::signals::signal的用法

吃力的讲完boost::signals的ppt,然后接着就是做练习题。通过讲ppt,发现有一句话说的真好:你自己知道是一回事,你能给别人讲明白又是另外一回事。真的有些东西你自己理解,但是用语言去很难表达,是不是用语言难以表达暴露出自己对所理解的东西不是真正的理解?。。。。orz,不过讲完ppt之后,真的对boost::singals的理解又加深一层。好了废话不多说了,现在来看两个习题(ppt的内容基本上是boost官方网站介绍boost::singlas用法的章节,这里不贴了):

第一题:

题目1:实现一个日常生活里出现的情景

描述:

     客人按门铃,门铃响,护士开门,婴儿惊醒后苦恼。

要求:

有至少两个护士和两个婴儿,并且某护士去开门是一个随机事件(随机数),只有当满足某个条件时才去开门,比如随机数randX满足500<randX%1000<999的时候才去开门,当然如果有一个护士去开门,剩下的护士就不用去开门了!门铃响,某个婴儿被惊醒也是一个随机事件,当满足一定条件时,这个婴儿醒来就哭叫,没醒的继续睡觉_~~_。

这个题就是想实现一个简单的观察这模式,如果不用boost::signals来实现,我们就得按照观察模式来写,首先肯定有一个观察者的基类,然后是n多派生观察者;其次要定义一个被观察者基类,然后就是m多被观察者,下面是一个实现:

<span style="font-size:14px;">namespace TestRing
{
	//观察者基类
	class CPerson
	{
	public:
		CPerson(const std::string& vName) : m_Name(vName) {}
		virtual ~CPerson()                {}

		//观察者收到通知(触发信号)的动作
		virtual void act()
		{
			std::cout<<"no action \n";
		}
		const std::string getName() const {return m_Name;}

	private:
		std::string m_Name;
	};

	//一个派生子类,实际观察者
	class CNurse : public CPerson
	{
	public:
		CNurse(const std::string& vName) : CPerson(vName) {}

		virtual void act() {std::cout<<"Nurse " <<getName()<<" come and open the door\n";}
	};

	//一个派生子类,实际观察者
	class CBaby : public CPerson{
	public:
		CBaby(const std::string& vName) : CPerson(vName) {}
		virtual void act() {std::cout<<"Baby "<<getName()<<" weak up and cry\n";}
	};

	//被观察者基类
	class CRing
	{
	public:
		CRing() {}
		virtual ~CRing() {}

		void ring()//触发信号
		{
			__notifyV();
		}

		//增加观察者
		void add(CPerson* vPerson) {m_Person.push_back(vPerson);}

	private:
		std::vector<CPerson*> m_Person;

		//通知所有观察者
		virtual void __notifyV()
		{
			std::vector<CPerson*>::iterator It = m_Person.begin();
			while (It != m_Person.end()) (*It++)->act();
		}
	};

	class CGuest : public CRing
	{
	public:
		CGuest() {}
		virtual ~CGuest() {}
	};

	void test()
	{
		CGuest Guest;
		CNurse Nurse("LiSi");
		CBaby  Baby("ZhangSan");

		Guest.add(&Nurse);
		Guest.add(&Baby);
		Guest.ring();//触发信号
	}
}</span>

为什么要用boost::signals呢?原因是上面这个代码耦合性强,用boost::signals可以来降低耦合性:

<span style="font-size:14px;">#pragma once

#include <algorithm>
#include <boost/ref.hpp>
#include <boost/bind.hpp>
#include <boost/signals2.hpp>

namespace Test_Signal_work
{
	class CGate
	{
		typedef boost::signals2::signal<void(bool, const std::string&)> signal_type;
		typedef signal_type::slot_type slot_type;
	public:
		boost::signals2::connection connect(const slot_type& vSlot)
		{
			return m_EnterOrLiveSig.connect(vSlot);
		}

		void enter(const std::string& vCarId)
		{
			m_EnterOrLiveSig(true, vCarId);
		}

		void leave(const std::string& vCarId)
		{
			m_EnterOrLiveSig(false, vCarId);
		}
	private:
		signal_type m_EnterOrLiveSig;
	};

	class CCarInformation
	{
		typedef boost::signals2::signal<void(const std::string&)> signal_type;
		typedef signal_type::slot_type slot_type;
		typedef std::vector<std::string> cars_type;
	public:
		boost::signals2::connection connect(const slot_type& vSlot)
		{
			return m_Sig.connect(vSlot);
		}

		void active(bool vEnter, const std::string& vCarId)
		{
			vEnter ? enter(vCarId) : leave(vCarId);
		}

		//不要这个也行,可以用boost::bind
		void operator()(bool vEnter, const std::string& vCarId)
		{
			active(vEnter, vCarId);
		}

	private:
		void enter(const std::string& vCarId)
		{
			cars_type::iterator It = std::find(m_CarsInfo.begin(), m_CarsInfo.end(), vCarId);
			if (It == m_CarsInfo.end())
			{
				m_CarsInfo.push_back(vCarId);
				std::cout << "car " << vCarId << " enter!" << std::endl;
			}
			else
			{
				m_Sig(vCarId);
			}
		}

		void leave(const std::string& vCarId)
		{
			cars_type::iterator It = std::find(m_CarsInfo.begin(), m_CarsInfo.end(), vCarId);
			if (It != m_CarsInfo.end())
			{
				std::cout << "car " << vCarId << " leave!" << std::endl;
				m_CarsInfo.erase(It);
			}
			else
			{
				m_Sig(vCarId);
			}
		}

	private:
		signal_type m_Sig;
		cars_type m_CarsInfo;
	};

	class CGuard
	{
	public:
		CGuard(const std::string& vName) : m_GuardName(vName) {}
		void active(const std::string& vCarId)
		{
			std::cout << m_GuardName << " knew that " << "there is an exception with car " << vCarId << std::endl;
		}

		void operator()(const std::string& vCarId)
		{
			active(vCarId);
		}
	private:
		std::string m_GuardName;
	};

	void test_fun_1()
	{
		CGuard ZS("ZhangSan");
		CGuard LS("LiSi");

		CCarInformation Info;

		CGate Gate1;
		CGate Gate2;

		Gate1.connect(boost::ref(Info));
		Gate2.connect(boost::ref(Info));

		Info.connect(LS);
		Info.connect(ZS);

		//测试1
		Gate1.enter("CA1001");
		Gate2.enter("CB1002");
		Gate1.leave("CB1002");
		//测试2
		Gate2.leave("CA1003");
		Gate1.enter("CA1004");
		Gate2.enter("CA1004");
		Gate1.leave("CA1004");
	}
}</span>

在看第二个例子:

题目2:模拟简单的停车场监视器

描述:

车辆进入或离开停车场时,监视器将收到一个通知信息(如唯一标记这辆车的车牌号,进入或离开时间,这里仅用车牌号),这样监视器才能跟踪每两车的进入和离开,并且监视器能够在有人进行欺骗行为时出发警报通知保安。

一个简单的停车场监视器可以用三个类来实现:CGate,CCarInformation,CGuard。


class
CGate

{

public:

void
enter(const
std::string&
vCarId);

void
leave(const
std::string&
vCarId);

};

CGate必须有enter和leave函数,把车辆的信息发送给CCarInformation。


class
CCarInformation

{

public:

void
active(bool
vEnter, const
std::string&
vCarId);

private:

std::vector<std::string>
m_CarsInfo;

};

CcarInformation收到CGate的信息时必须有一个active来采取相应的措施,比如某辆车的信息异常侧发出警报通知CGuard。


class
CGuard

{

public:

void
active(const
std::string&
vCarId);

private:

std::string
m_GuardName;

};

如果CcarInformation发出警报则CGuard必须做出反应。

要求实现功能:

   停车场有两个门,每个门都可以进出,并且把车辆的出入信息通知给CCarInformation来跟踪每辆车。同一辆车两次进入(或两次离开)时,发出警报通知所有保安。每个门有一个保安。

测试样例:

  


int
main()

{

//测试1

Gate1.enter("CA1001");

Gate2.enter("CB1002");

Gate1.leave("CB1002");

//测试2

Gate2.leave("CA1003");

Gate1.enter("CA1004");

Gate2.enter("CA1004");

Gate1.leave("CA1004");

}

测试1输出:

car CA1001 enter!

car CB1002 enter!

car CB1002 leave!

测试2输出:

ZhanSan knew that there is an exception with car CA1003!

LiSi knew that there is an exception with car CA1003!

car CA1004 enter!

ZhanSan knew that there is an exception with car CA1004!

LiSi knew that there is an exception with car CA1004!

car CA1004 leave!

这个例子比前一个例子稍微复杂:

#pragma once

#include <algorithm>
#include <boost/ref.hpp>
#include <boost/bind.hpp>
#include <boost/signals2.hpp>

namespace Test_Signal_work
{
	class CGate
	{
		typedef boost::signals2::signal<void(bool, const std::string&)> signal_type;
		typedef signal_type::slot_type slot_type;
	public:
		boost::signals2::connection connect(const slot_type& vSlot)
		{
			return m_EnterOrLiveSig.connect(vSlot);
		}

		void enter(const std::string& vCarId)
		{
			m_EnterOrLiveSig(true, vCarId);
		}

		void leave(const std::string& vCarId)
		{
			m_EnterOrLiveSig(false, vCarId);
		}
	private:
		signal_type m_EnterOrLiveSig;
	};

	class CCarInformation
	{
		typedef boost::signals2::signal<void(const std::string&)> signal_type;
		typedef signal_type::slot_type slot_type;
		typedef std::vector<std::string> cars_type;
	public:
		boost::signals2::connection connect(const slot_type& vSlot)
		{
			return m_Sig.connect(vSlot);
		}

		void active(bool vEnter, const std::string& vCarId)
		{
			vEnter ? enter(vCarId) : leave(vCarId);
		}

		//不要这个也行,可以用boost::bind
		void operator()(bool vEnter, const std::string& vCarId)
		{
			active(vEnter, vCarId);
		}

	private:
		void enter(const std::string& vCarId)
		{
			cars_type::iterator It = std::find(m_CarsInfo.begin(), m_CarsInfo.end(), vCarId);
			if (It == m_CarsInfo.end())
			{
				m_CarsInfo.push_back(vCarId);
				std::cout << "car " << vCarId << " enter!" << std::endl;
			}
			else
			{
				m_Sig(vCarId);
			}
		}

		void leave(const std::string& vCarId)
		{
			cars_type::iterator It = std::find(m_CarsInfo.begin(), m_CarsInfo.end(), vCarId);
			if (It != m_CarsInfo.end())
			{
				std::cout << "car " << vCarId << " leave!" << std::endl;
				m_CarsInfo.erase(It);
			}
			else
			{
				m_Sig(vCarId);
			}
		}

	private:
		signal_type m_Sig;
		cars_type m_CarsInfo;
	};

	class CGuard
	{
	public:
		CGuard(const std::string& vName) : m_GuardName(vName) {}
		void active(const std::string& vCarId)
		{
			std::cout << m_GuardName << " knew that " << "there is an exception with car " << vCarId << std::endl;
		}

		void operator()(const std::string& vCarId)
		{
			active(vCarId);
		}
	private:
		std::string m_GuardName;
	};

	void test_fun_1()
	{
		CGuard ZS("ZhangSan");
		CGuard LS("LiSi");

		CCarInformation Info;

		CGate Gate1;
		CGate Gate2;

		Gate1.connect(boost::ref(Info));
		Gate2.connect(boost::ref(Info));

		Info.connect(LS);
		Info.connect(ZS);

		//测试1
		Gate1.enter("CA1001");
		Gate2.enter("CB1002");
		Gate1.leave("CB1002");
		//测试2
		Gate2.leave("CA1003");
		Gate1.enter("CA1004");
		Gate2.enter("CA1004");
		Gate1.leave("CA1004");
	}
}
时间: 2024-11-08 23:42:15

boost::signals::signal的用法的相关文章

boost::signals::signal的使用方法

吃力的讲完boost::signals的ppt.然后接着就是做练习题. 通过讲ppt,发现有一句话说的真好:你自己知道是一回事.你能给别人讲明确又是另外一回事.真的有些东西你自己理解,可是用语言去非常难表达,是不是用语言难以表达暴露出自己对所理解的东西不是真正的理解?... . orz.只是讲完ppt之后,真的对boost::singals的理解又加深一层.好了废话不多说了,如今来看两个习题(ppt的内容基本上是boost官方站点介绍boost::singlas使用方法的章节,这里不贴了): 第

vs2013 boost signals

#include "stdafx.h" #include <boost/signals2/signal.hpp> #include <iostream> using namespace std; void func() { std::cout << "Hello, world!" << std::endl; } void slots1() { cout << "slots1 call"

观察者模式与Boost.Signals

1)  观察者模式定义 略,各种设计模式的书上都有定义. 2)  观察者模式一般实现 观察者模式一般实现,都是“被观察者”保存一个“观察者”的列表,循环这个列表来通知“观察者”.代码,其中使用了boost的智能指针shared_ptr: [cpp] view plaincopy #include <iostream> #include <list> #include "boost/shared_ptr.hpp" using namespace std; usin

boost::mpl::eval_if的用法

最近看boost的时候总是遇见这个eval_if,不知道啥意思,就没法看下去了,比如 前篇文章boost::serialization 拆分serialize函数分析时就出现这样一段代码: template<class Archive, class T> inline void split_member(Archive & ar, T & t, const unsigned int file_version) { typedef BOOST_DEDUCED_TYPENAME m

boost::any的一般用法

01.#include <iostream> 02.#include <list> 03.#include <boost/any.hpp> 04. 05.typedef std::list<boost::any> list_any; 06. 07.//关键部分:可以存放任意类型的对象 08.void fill_list(list_any& la) 09.{ 10.    la.push_back(1000);//存放常数 11.    la.push

boost信号量 boost::interprocess::interprocess_semaphore的用法

使用方法首先给信号量初始化赋值,可以根据需要设定需要的值,之前在写项目的过程中用这个控制下载的线程个数. 1 boost::interprocess::interprocess_semaphore m_semaphore(0); 然后就是pv操作了,v操作就只有一个post(),post()一次,信号量加1.p操作有三个,看函数名字都很明显知道是什么意思, wait(),try_wait() ,timed_wait(const boost::posix_time::ptime&abs_time)

windows下boost库的基本用法

由于boost都是使用模板的技术,所以全部代码都是写在一个.hpp头文件里.这样boost中的大部分内容是不须要编译生成对应的链接库,仅仅须要设置以下的包括文件夹(或者设置一下环境变量),在源文件里包括对应的头文件就能够使用了. 少部分库须要生成链接库来使用. 以下介绍完整安装boost库的方法: 1.首先到boost官网去下载最新的版本号的boost库: http://www.boost.org/ 2.解压文件.在命令提示符中打开到boost库的根文件夹下: 双击bootstrap.bat文件

boost.multi_array 的基本用法(2)

//made by davidsu33 //2014-9-14 11:51 #include "stdafx.h" #include <boost/config.hpp> #include <boost/multi_array/extent_gen.hpp> #include <boost/multi_array.hpp> #include <boost/pool/pool.hpp> #include <boost/pool/poo

Boost Log 基本用法

Boost Log 基本用法 flyfish 2014-11-5 根据boost提供的代码示例,学习Boost Log 的基本用法 前提 boost版本boost_1_56_0 示例代码文件夹 boost_1_56_0\libs\log\example\basic_usage 使用的单词很形象,整个过程就像流水一样 假设要输出的日志比作水 水                     (Hello, World!) 水槽                 (sink) 流向哪里        (co