事件基本概念

  • 操作系统或应用程序内部发生某件事,程序的某个组件需要响应该事件,并进行特定处理

面向对象架构中,事件响应函数最可能为成员函数

  • 问题:指向类成员函数的指针不能转换为哑型指针void *,也不能随意转换为指向另一个类的成员函数的指针
  • 解决方案:使用指向指向类成员函数的指针的指针

实现策略:事件委托模型

  • Event类模板:管理事件响应者对象,实现事件多播
  • EventResponsor类模板:响应者对象与响应者行为配对
  • Empty类:委托模型和指针转换
#include <iostream>
#include <vector>
using namespace std;
//空类,用于指代响应者对象
class Empty{};
//事件响应者类模板,保存特定事件的响应者与响应行为
template<typename EventAction> class EventResponsor
{
public:
EventResponsor():actor(NULL),action(NULL) {}
EventResponsor(Empty *actor,EventAction *action):actor(actor),action(action){}
friend bool operator==(const EventResponsor &lhs, const EventResponsor &rhs)
{
return lhs.actor == rhs.actor && *lhs.action == *rhs.action;
}
public://公开的数据成员,以方便使用者
Empty *actor;
EventAction *action;
};//template<typename EventAction> class EventResponsor
//事件类模板,用于管理特定事件的所有响应者
template<typename EventAction> class Event
{
public:
typedef vector<EventResponsor<EventAction> >EventResponsors;
typeder typename vector<EventResponsor<EventAction> >::iterator EventIterator;
public:
virtual ~Event()
{
for (EventIterator it = this->_ers.begin(); it != this->_ers.end(); ++it)
{
delete it->action, it->action = NULL;
}
}
EventResponsors & GetResponsors() { return this->_ers; } //事件绑定,将实际响应者和响应行为挂接到事件响应者对象上
template<typename Responsor, typename Action>
void Bind(Responsor *actor, Action action)
{
Action *act = new Action(action);
EventResponsor<EventAction> er((Empty*)actor, (EventAction*)act);
bool unbound = true;
for (EventIterator it = this->_ers.begin(); it != this->_ers.end(); ++it)
{
if (*it == er)//发现重复的事件响应者,说明已绑定
{
unbound = false;
break;
}
}
if (unbound)
{
this->_ers.push_back(er);
}
else
{
delete er.action, er.action = NULL;
}
}
//解除事件绑定,删除事件响应者对象
template<typename Responsor,typename Action>
void Unbind(Responsor *actor, Action action)
{
Action *act = new Action(action);
EventResponsor<EventAction> er((Empty*)actor, (EventAction *)act);
for (EventIterator it = this->_ers.begin(); it != this->_ers.end(); ++it)
{
if (*it == er)//找到待删除的事件响应者对象
{
delete it->action, this->_ers.erase(it); break;
}
}
delete er.action, er.action = NULL;
}
private:
EventResponsor _ers;
};//template<typename EventAction> class Event
//定义事件委托模型,指向类成员函数的指针
typedef Empty EventDelegator;
typedef void(EventDelegator::*ValueChanged)(int value, void *tag);
//触发者
class Trigger
{
public:
Trigger() :_value() {}
void SetValue(int value, void *tag);
int GetValue() { return _value; }
public:
//值变化事件,公开属性,方便在类外设定
Event<ValueChanged> value_changed;
private:
int _value;
};
//设定值,遍历特定事件的响应对象列表,逐一触发值变更事件
void Trigger::SetValue(int value, void *tag)
{
if (_value == value)
{
return;
}
_value = value;
Event<ValueChanged>::EventResponsors ers;
ers = this->value_changed.GetResponsors();
if (!ers.empty())
{
Event<ValueChanged>::EventIterator it;
for ( it = ers.begin(); it != ers.end(); ++it)
{
((it->actor)->*(*(it->action)))(value, tag);//响应事件
}
}
}
//行动者
class Actor
{
public:
//侦听事件,绑定本对象的事件响应函数到侦听的事件
void Listen(Trigger *trigger)
{
trigger->value_changed.Bind(this, &Actor::OnValueChanged);
}
//停止侦听,从侦听的事件中取消本对象的事件响应活动
void Unlisten(Trigger *trigger)
{
trigger->value_changed.Unbind(this, &Actor::OnValueChanged);
}
//值变更事件的响应函数
void OnValueChanged(int value, viod *tag)
{
cout << reinterpret_cast<char *>(tag) << value << "." << endl;
}
}; int main()
{
const char *s = "Now the value is";
Trigger t;
Actor a1, a2; a1.Listen(&t);
a2.Listen(&t); cout << "Listening..." << endl;
t.SetValue(, reinterpret_cast<void *>(const_cast<char *>(s))); a2.Unlisten(&t);
cout << "Listening again..." << endl;
t.SetValue(, reinterpret_cast<void *>(const_cast<char *>(s)));
return ;
}

C++学习笔记38:事件机制的更多相关文章

  1. NodeJS学习笔记 (21)事件机制-events(ok)

    模块概览 events模块是node的核心模块之一,几乎所有常用的node模块都继承了events模块,比如http.fs等. 模块本身非常简单,API虽然也不少,但常用的就那么几个,这里举几个简单例 ...

  2. java学习笔记09--反射机制

    java学习笔记09--反射机制 什么是反射: 反射是java语言的一个特性,它允许程序在运行时来进行自我检查并且对内部的成员进行操作.例如它允许一个java的类获取他所有的成员变量和方法并且显示出来 ...

  3. Storm学习笔记 - 消息容错机制

    Storm学习笔记 - 消息容错机制 文章来自「随笔」 http://jsynk.cn/blog/articles/153.html 1. Storm消息容错机制概念 一个提供了可靠的处理机制的spo ...

  4. 学习笔记---Javascript事件Event、IE浏览器下的拖拽效果

    学习笔记---Javascript事件Event.IE浏览器下的拖拽效果     1. 关于event常用属性有returnValue(是否允许事件处理继续进行, false为停止继续操作).srcE ...

  5. Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle<T>

    Caliburn.Micro学习笔记目录 今天 说一下Caliburn.Micro的IEventAggregator和IHandle<T>分成两篇去讲这一篇写一个简单的例子 看一它的的实现 ...

  6. iOS学习笔记--触摸事件

    最近空闲时间在学习iOS相关知识,几周没有更新文章了,今天总结下这些天的学习内容,也整理下iOS的学习笔记,以便以后查阅翻看- iOS中的事件可以分为3大类型: 触摸事件 加速计事件 远程控制事件 响 ...

  7. java学习笔记13--反射机制与动态代理

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...

  8. [JS学习笔记]Javascript事件阶段:捕获、目标、冒泡

    当你在浏览器上点击一个按钮时,点击的事件不仅仅发生在按钮上,同时点击的还有这个按钮的容器元素,甚至也点击了整个页面. 事件流 事件流描述了从页面接收事件的顺序,但在浏览器发展到第四代时,浏览器开发团队 ...

  9. vue学习笔记(四)事件处理器

    前言 在上一章vue学习笔记(三)class和style绑定的内容中,我们学习了如何在vue中绑定class和style,介绍了常用的绑定方法,class的数组绑定和对象绑定以及style的数组绑定和 ...

  10. JavaScript高级程序设计学习笔记之事件

    1.事件流 事件流描述的是从页面中接收事件的顺序. 事件冒泡 IE的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播 ...

随机推荐

  1. vuejs初学入门环境搭建

    一.Nodejs:    1.安装下载:http://nodejs.cn/download/    2.Node.js安装配置: http://www.runoob.com/nodejs/nodejs ...

  2. 基于Apache的阿里云部署Node.js服务器(Windows环境)

    1 前言 由于nodejs项目对方开放了多个端口,而且阿里云上的Apache服务器(windows)已经挂载了网站,此时需要把此项目也挂上去,网上查询资料,方法略少,基本是基于nginx版本的. 2  ...

  3. python-找出100以内的质数

    质数:就是只能被1和本身整除的数,1除外,如2,3,5,7,11,13等等 ##求一百以内的质数(1和本身除尽的数)if __name__ == '__main__': list=[] flag=Fa ...

  4. Python-浮动 清浮动

    # 浮动布局 ## 一.display总结 ```css/* inline *//*1.同行显示, 就相当于纯文本, 当一行显示不下, 如就是一个字显示不下,那么显示不下的那一个字就会自动换行,和纯文 ...

  5. compile php with openssl on mac osx error 填坑

    从源码手动编译 PHP 时出现如下错误:           Default   1 2 3 4 5 6 7 8 9 10 11 12 13 14 Undefined symbols for arch ...

  6. python 全栈开发,Day104(DRF用户认证,结算中心,django-redis)

    考试第二部分:MySQL数据库 6.  MySQL中char和varchar的区别(1分) char是定长,varchar是变长. char的查询速度比varchar要快. 7.   MySQL中va ...

  7. ubuntu 12.04 安装 openssh-server 失败,请问怎么该弄?

    $ sudo apt-get install openssh-server Reading package lists... Done Building dependency tree Reading ...

  8. poj 3233 S = A + A^2 + A^3 + … + A^k A是一个n X n矩阵 (矩阵快速幂)

    S = A + A^2 + A^3 + … + A^k A是一个n*n矩阵 Sample Input 2 2 4 //n k MOD0 11 1Sample Output 1 22 3 先求 I +  ...

  9. hdu 2197 求长度为n的本原串 (快速幂+map)

    Problem Description由0和1组成的串中,不能表示为由几个相同的较小的串连接成的串,称为本原串,有多少个长为n(n<=100000000)的本原串?答案mod2008.例如,10 ...

  10. hdu 1542

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 题意: 求所给矩形的覆盖面积 题解: 利用扫描线的思想,先将坐标离散化,之后以y轴分成多个矩形求解, ...