吃力的讲完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");
}
}

boost::signals::signal的使用方法的更多相关文章

  1. 观察者模式与Boost.Signals

      1)  观察者模式定义 略,各种设计模式的书上都有定义. 2)  观察者模式一般实现 观察者模式一般实现,都是“被观察者”保存一个“观察者”的列表,循环这个列表来通知“观察者”.代码,其中使用了b ...

  2. vs2013 boost signals

    #include "stdafx.h" #include <boost/signals2/signal.hpp> #include <iostream> u ...

  3. boost之signal的使用

    文章目录 简介 代码 模板实现: 测试代码 运行结果 简介 boost是C++的一个扩展库,被称为C++准标准库,里面的组件很丰富,并且引用方便,85%的组件只需要引用头文件即可使用. 并且在嵌入式系 ...

  4. windows下boost库的基本使用方法

    因为boost都是使用模板的技术,所以所有代码都是写在一个.hpp头文件中.这样boost中的大部分内容是不需要编译生成相应的链接库,只需要设置下面的包含目录(或者设置一下环境变量),在源文件中包含相 ...

  5. boost之signal

    boost里的signal是一个模板类,不区分信号种类,产生信号统一用()调用操作符. 1.回调普通函数代码示例: #include <iostream> #include <str ...

  6. boost::filesystem经常使用使用方法具体解释

    提示: filesystem库提供了两个头文件,一个是<boost/filesystem.hpp>,这个头文件包括基本的库内容.它提供了对文件系统的重要操作. 同一时候它定义了一个类pat ...

  7. boost::mpl::eval_if的使用方法

    近期看boost的时候总是遇见这个eval_if,不知道啥意思,就没法看下去了,比方 前篇文章boost::serialization 拆分serialize函数分析时就出现这样一段代码: templ ...

  8. boost::any的一般使用方法

    01.#include <iostream>    02.#include <list>    03.#include <boost/any.hpp>    04. ...

  9. Boost的某些库还是需要生成二进制的库的,必须安装才行,以及使用库的方法

    头文件就是库使用者最常问的问题就是“我该怎么安装Boost”,这个也是我一开始最关心的问题,Boost这点做的很好,将大部分实现都封装在头文件里,所以对于一些基本的Boost库,其实是不需要安装的,只 ...

随机推荐

  1. zoj 1107 FatMouse and Cheese(记忆化搜索)

    题目链接:点击链接 题目大意:老鼠从(0,0)出发,每次在同一个方向上最多前进k步,且每次到达的位置上的数字都要比上一个位置上的数字大,求老鼠经过的位置上的数字的和的最大值 #include<s ...

  2. qt新进程工作目录的设置(工作目录确实是被子进程继承的,但也可以设置)

    经过试验,qt启动一个新的进程时,这个进程的工作目录是继承父进程的,无论是通过start还是startDetached来启动. 其实对于linux系统,qt底层应该也是调用fork.exec之类的函数 ...

  3. 【改了一天的拓扑排序】POJ 1094——Sorting It All Out

    来源:点击打开链接 不知道怎么回事,wa了整整一天..在绝望的时候AC了. 重点是分步处理和三种情况的判断. 1.判断是否成环,成环了直接输出错误信息. 2.然后一条边一条边的加入,进行拓扑排序,如果 ...

  4. Eclipse中快捷键的使用

    1:引入包   ctrl+shift+o 2:对输入进行提示:Alt+/ 3: 全局搜索:crtrl + h 4:Eclipse创建方法快捷键Alt+shift+M 5:Eclipse创建局部变量快捷 ...

  5. ThinkPhp学习11

    原文:ThinkPhp学习11 一.模板的使用        (重点) a.规则 模板文件夹下[TPL]/[分组文件夹/][模板主题文件夹/]和模块名同名的文件夹[Index]/和方法名同名的文件[i ...

  6. 如何理解java回电话

    同android中间Button的setOnClickListener这个回调案例: Button button = (Button)this.findViewById(R.id.button); b ...

  7. WebService-03-使用CXF开发服务端和客户端

    写在前面的话 前面两节说了使用Java提供的包开发服务端和客户端,现在使用CXF来开发,CXF提供了两个类发而服务,一个是ServerFactoryBean,另一个是JaxWsServerFactor ...

  8. NET之全平台一体化

    NET之全平台一体化的体验 一.前言 近来利用空闲时间研究了一下Xamarin的技术,想想既然提供了如此好的支持,就该尝试一切可能,来一个”大小通吃“. 何为全平台:APP包括Android.IOS. ...

  9. uva 11355(极角计算)

    传送门:Cool Points 题意:给一个圆心为原点的圆和一些线段,问所有线段两端点与圆心连线构成的角度总和占总360度的百分比. 分析:首先将所有线段的两端点变成极角,然后排序(范围[-PI,PI ...

  10. UNIX 网络编程之线程

    概述: 实现并发服务器一般都是父进程accept一个连接,然后fork一个子进程,该子进程处理与该连接对端的客户之间的通信.但是fork是昂贵,耗资源和时间.而线程是轻量级线程,它的创建比进程的创建块 ...