`
isiqi
  • 浏览: 16349071 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

C++实现事件机制

阅读更多

委托是一种很实用的设计方法,一个模块可以将某些事情委托给其他实体去做,而对于模块本身不需要知道受委托的实体是什么,它只知道这个实体遵循某种接口规范。回调函数可以认为是一种委托,它在Windows编程中起了非常重要的作用。

委托的一个重要应用是事件机制,假设有类A负责加载数据,类B用于实时显示A的加载进度,那么A必须向B引发一些事件,以表明它的加载进度。要实现这种机制可以用观察者模式,Java即使用观察者模式来实现事件监听的。Delphi使用了类似回调函数的技术来实现事件,这样也有一些好处,就是简单高效,对于一些轻量级的应用还是非常合适的。

C++如何实现事件,当然可以用观察者模式来实现,不过这里要介绍另一种方法,就是用成员函数指针,这种方法更类似于Delphi的事件,优点是简单高效。

下面是我写的两个源文件,对通用事件提供了支持,其中涉及到成员函数指针的知识,我就不班门弄斧了,直接给就出源代码如下:

EventUtils.h

#ifndef EVENTUTILS_H_

#define EVENTUTILS_H_

// 用于欺骗编译器,传递This指针

class CMemFunObj

{

};

// 通用函数类型

typedef void (CMemFunObj:: *PFNMEMFUN)();

// 成员函数结构

typedef struct tagMEMBERFUN {

CMemFunObj *Self;

PFNMEMFUN pfnAddr;

} MEMBERFUN, *PMEMBERFUN;

// 生成成员函数结构

MEMBERFUN MakeMemberFun(CMemFunObj *Self, PFNMEMFUN pfnAddr);

// 宏:生成成员函数结构

#define MAKEMEMFUN(Self, pfnAddr) \

MakeMemberFun((CMemFunObj*)Self, (PFNMEMFUN)pfnAddr)

// 宏:回调成员函数,FunType为具体函数类型,MemFun为成员函数结构

#define CALLMEMFUN(FunType, MemFun) \

(MemFun.Self->*(FunType)MemFun.pfnAddr)

// 宏:判断成员函数结构是否有值

#define ISMEMFUNASSIGNED(MemFun) \

(MemFun.Self != NULL) && (MemFun.pfnAddr != NULL)

#endif // EVENTUTILS_H_

EventUtils.cpp

#include "EventUtils.h"

// 生成成员函数结构

MEMBERFUN MakeMemberFun(CMemFunObj *Self, PFNMEMFUN pfnAddr)

{

MEMBERFUN Memfun;

Memfun.pfnAddr = pfnAddr;

Memfun.Self = Self;

return Memfun;

}

其中比较有意思的是用CMemFunObj来做对象绑定,这个类会欺骗编译器,使编译将This指针传进成员函数;MEMBERFUN是成员函数结构,一个成员函数要成功调用必须有两个要素,一个是绑定的对象,一个是函数地址,这就是MEMBERFUN的内容。

下面看看如何用这个单元,有一个CRunner类,提供一个Run方法,我们要实现的是监控Run的进度。

首先声明CRunner,声明进度事件类型,以及在CRunner保存一个事件类型的成员:

#ifndef RUNNER_H_

#define RUNNER_H_

#include "EventUtils.h"

// 进度事件类型

typedef void (CMemFunObj:: *RUNPROCESS)(int nPercent);

class CRunner

{

public:

CRunner();

virtual ~CRunner();

// 设置事件结构

void SetOnProcess(MEMBERFUN OnRunProcess);

// 开始运行

void Run();

private:

MEMBERFUN m_OnRunProcess;

};

#endif // RUNNER_H_

接着实现CRunner,并看看Run如何调用事件:

#include "Runner.h"

#include <string.h>

#include <windows.h>

CRunner::CRunner()

{

memset(&m_OnRunProcess, 0, sizeof(m_OnRunProcess));

}

CRunner::~CRunner(){}

void CRunner::SetOnProcess( MEMBERFUN OnRunProcess )

{

m_OnRunProcess = OnRunProcess;

}

void CRunner::Run()

{

int nTime = 0;

while ((nTime++) < 100)

{

Sleep(10);

if (ISMEMFUNASSIGNED(m_OnRunProcess))

CALLMEMFUN(RUNPROCESS, m_OnRunProcess)(nTime);

}

}

Run函数用ISMEMFUNASSIGNED宏判断m_OnRunProcess是否被赋值,如果有,则用CALLMEMFUN宏来调用具体的事件。关于这几个宏,可以参考EventUtils.h

CRunner支持事件之后,来看看事件如何被接收:

#include "EventUtils.h"

#include "Runner.h"

#include <iostream>

using namespace std;

class EventSink

{

public:

void RunProcess(int Percent)

{

cout<<Percent<<endl;

}

};

int main()

{

EventSink es;

CRunner R;

R.SetOnProcess(MAKEMEMFUN(&es, es.RunProcess));

R.Run();

return 0;

}

MAKEMEMFUN用于合成一个成员函数结构体,调用R.SetOnProcess之后,es便能够监听CRunner的进度事件。

使用这种技术来实现事件机制应该说是通用的,你可以整合到如MFC这类应用程序框架中。该技术的优点是高效,但缺点也很明显,就是只支持单点事件,如果要实现多点事件则要做更多的工作。

分享到:
评论

相关推荐

    C++实现C#事件机制

    本文将深入探讨如何在C++中实现C#事件机制的关键元素,并介绍与之相关的函数指针和尾随参数的概念。 首先,让我们了解C#中的事件和委托。在C#中,事件是一种特殊的委托(delegate)类型,用于封装多个方法,这些...

    c++实现的对象事件驱动机制

    总的来说,C++实现的事件驱动机制虽然比使用像Java或.NET等提供内置事件支持的语言更复杂,但它允许更灵活的设计,并且可以在跨平台项目中使用。这种机制对于构建用户界面、异步编程和游戏引擎等场景非常有用。通过...

    C++反射机制实现

    在讨论C++反射机制实现的过程中,我们首先需要明确反射机制的概念和分类。反射的定义源自人工智能领域,它主要涉及到两种反射结构:结构反射和计算反射。结构反射侧重于元类与类之间的关系,计算反射则关注于计算...

    C++中事件机制的简洁实现

    事件模型是被广泛使用的好东西,但是C++标准库里没有现成的,其他实现又复杂或者不优雅,比如需要使用宏。现在VC11可以用在XP下了,那么痛快的拿起C++11提供的先进设施组合出一个轻便的实现吧。  为了达到简洁的...

    C++消息机制

    C++并没有内置的消息传递系统,但可以通过多种技术实现类似的功能,如函数调用、继承、多态、模板、信号与槽机制等。下面我们将详细探讨这些知识点。 1. 函数调用: 在C++中,最基本的消息传递方式是通过函数调用来...

    C++Event机制的简单实现

    本文将详细介绍如何在C++中实现一个简单的事件机制。 ##### 1. 事件 在面向对象编程中,“事件”通常指的是对象的状态或属性发生变化,或者是对象接收到某些动作时,该对象会向外发出通知。例如,在图形用户界面...

    c++实现委托和事件

    这样,我们就使用C++的`std::function`和`std::bind`实现了类似于C#中的委托和事件机制。这种方法虽然没有C#那样的语法糖,但依然能够提供功能强大的回调管理和事件通知。在实际项目中,这种机制可以用于实现如UI...

    c++ PImpl实现机制

    (1)它让声明和实现进行解耦,在项目开发时,如果很多文件引用了该头文件,如果头文件改变了一些实现,那么在编译时,所有引用的文件也得重新编译一次,增加了c++程序的编译时间, 如果把实现用一个指针进行声明,...

    c++ 垃圾回收机制

    3. **垃圾回收机制(c++实现).mht** - 这个文件很可能直接讨论了如何在C++中实现一个垃圾回收系统,可能包括具体的代码示例和理论解释。 通过这些资源,我们可以深入学习C++如何通过自定义的方式来实现垃圾回收,...

    C++反射机制

    本文将深入探讨C++中的反射机制,分析其实现原理,并提供一种基于工厂模式的实例化方法。 #### C++反射机制的缺失与挑战 与C#和Java相比,C++的标准库并未直接支持反射功能。这意味着,开发者不能直接根据类名动态...

    C++插件机制的实现

    在本教程中,我们将探讨如何在Visual Studio 2013环境下实现C++插件机制。 1. **动态链接库(DLL)**:DLL是Windows操作系统中的一个关键组件,它包含可以被多个程序共享的函数和资源。在C++中,我们可以通过创建...

    C++ 消息映射机制深度探索

    C++ 消息映射机制深度探索

    C++实现mqtt协议

    总的来说,C++实现MQTT协议主要涉及理解MQTT协议的基本概念,选择合适的客户端库(如Eclipse Paho),以及正确地使用库提供的接口来建立连接、订阅和发布消息。通过这种方式,你可以构建出高效且可靠的物联网应用,...

    C++实现SIP协议栈

    C++实现SIP协议栈时,需要对这些消息进行解析和构建。 1. **消息解析**:在C++中,可以使用字符串处理函数或正则表达式解析SIP消息头和消息体。头部分通常包含方法、URI、版本、状态代码等关键信息,需要正确解析并...

    C++ 实现银行排队服务模拟

    C++ 动态内存管理是指 C++ 中的内存管理机制,本实验中,我们将使用 C++ 动态内存管理来实现银行排队服务模拟系统。 ### 10. CPU 资源争夺模型 CPU 资源争夺模型是一种描述 CPU 资源争夺的数学模型,本实验中,...

    C++ - 使用标准库实现事件和委托,信号和槽机制

    在C++编程中,事件和委托是用于对象间通信的重要机制。它们通常被用来实现响应式编程,使得当一个对象的状态发生改变时,其他对象能够自动接收到通知并执行相应的操作。这种机制在图形用户界面(GUI)开发、并发编程...

    C++ 实现WebSocket 服务器

    在本项目中,我们使用C++来实现一个WebSocket服务器,借助了libuv库来处理TCP层面的基础工作,并利用gbase作为辅助工具。 ### C++ 语言特性 C++是一种静态类型的、编译式的、通用的、大小写敏感的、不仅支持过程化...

    C++中虚函数的实现机制

    ### C++中虚函数的实现机制 #### 一、虚函数的概念及其重要性 在C++编程语言中,虚函数是实现多态性的关键机制之一。多态性是指同一个操作作用于不同的对象,可以有不同的解释,进而触发不同的行为。在面向对象...

Global site tag (gtag.js) - Google Analytics