基于泛型类模块,使类成员函数作为回调函数
来源:互联网 发布:条码打印软件使用方法 编辑:程序博客网 时间:2024/06/15 07:44
1. FuncCache
此类用于存放,类和函数信息。关键在于对函数参数的处理,写得妙。因为,类中类的成员,在使用后自动销毁,可以使得函数可以反复调用。类成员buffer,相当于一个栈,可用于在放任何数据(如:类指针、函数指针、参数指针)。类成员func,存放MFuncCall_1的静态成员函数。为什么不把这个静函数直接作为成员函数?因为可以用这个函数作为接口,方便用户自定义!
2. MFuncCall_1
用此类编写与目标回调函数最后执行的代码。读取预存信息:类指针、类成员函数指针、参数值。最后执行这个函数。
3. L_Signal_1继承于L_SignalRoot
这个类主要是封装FuncCache的操作,使用Map可存放多个类的回调函数。
4. EventCallerA和EventCallerB
这两个类主要是用来做测试用例。
// Delegate.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <iostream>#include <map>using namespace std;typedef unsigned int uint;typedef unsigned char uchar;//////////////////////////////////////////////////////////////////////////////////// \class FuncCache/// \brief 函数对象寄存器/////////////////////////////////////////////////////////////////////////////////template <typename ReturnType>class FuncCache{ static const int SIZE = 48; typedef ReturnType (*func_caller)(FuncCache*); /// \class MemberFuncAssist /// \brief 对象成员函数寄存器的辅助器 class FuncCacheAssist { public: /// \brief 构造函数,初始化。 FuncCacheAssist(FuncCache* pFunc) { m_Size = 0; m_pFunc = pFunc; // 读取用偏移必须归位 m_pFunc->m_Cur = 0; } /// \brief 析构函数。 ~FuncCacheAssist(void) { // 弹出以前压入的参数 if (m_Size > 0) m_pFunc->Pop(m_Size); } /// \brief 压入指定大小的数据。 uint Push(const void* pData, uint size) { m_Size += size; return m_pFunc->Push(pData, size); } /// 压入参数的大小 int m_Size; /// 对象成员函数寄存器 FuncCache* m_pFunc; };public: /// \brief 构造函数,初始化。 FuncCache(func_caller func) { m_Size = 0; m_Cur = 0; m_Func = func; } /// \brief 压入指定大小的数据。 uint Push(const void* pData, uint size) { size = (size <= SIZE - m_Size)? size : (SIZE - m_Size); memcpy(m_Buffer + m_Size, pData, size); m_Size += size; return size; } /// \brief 弹出指定大小的数据。 uint Pop(uint size) { size = (size < m_Size)? size : m_Size; m_Size -= size; return size; } /// \brief 读取指定大小的数据,返回指针。 void* Read(uint size) { m_Cur += size; return (m_Buffer + m_Cur - size); } /// \brief 执行一个参数的函数。 ReturnType Execute(const void* pData) { // 用辅助结构控制 FuncCacheAssist assist(this); // 压入参数 assist.Push(&pData, sizeof(void*)); // 执行函数 return m_Func(this); }protected: /// 对象,函数,参数指针的缓冲区 uchar m_Buffer[SIZE]; /// 缓冲区大小 uint m_Size; /// 缓冲区读取用的偏移 uint m_Cur; /// 操作函数的指针 func_caller m_Func;};//////////////////////////////////////////////////////////////////////////////////// \class MFuncCall_1/// \brief 一个参数的成员函数执行体/////////////////////////////////////////////////////////////////////////////////template <typename ReturnType, typename Caller, typename Func, typename ParamType>class MFuncCall_1{public: /// \brief 执行一个参数的成员函数。 static ReturnType MFuncCall(FuncCache<ReturnType>* pMFunc) { // 获得对象指针 Caller* pCaller = *(Caller**)pMFunc->Read(sizeof(Caller*)); // 获得成员函数指针 Func func = *(Func*)pMFunc->Read(sizeof(Func)); // 获得参数的指针 ParamType* pData = *(ParamType**)pMFunc->Read(sizeof(ParamType*)); // 执行成员函数 return (pCaller->*func)(*pData); }};//////////////////////////////////////////////////////////////////////////////////// \class L_SignalRoot/// \brief 类型检查严格的事件委托器基类/////////////////////////////////////////////////////////////////////////////////template <typename ReturnType>class L_SignalRoot{public: /// \brief 指定事件名,卸载指定对象的事件委托器。 template <typename Caller> void MFuncUnregister(Caller* pCaller) { func_map& func_list = m_MemberFuncMap; func_map::iterator it = func_list.find(pCaller); if (it != func_list.end()) func_list.erase(it); } /// \brief 清空所有事件委托器。 void MFuncClear(void) { m_MemberFuncMap.clear(); }protected: typedef map< void*, FuncCache<ReturnType> > func_map; /// 事件名和绑定的事件委托器的列表 func_map m_MemberFuncMap;};//////////////////////////////////////////////////////////////////////////////////// \class L_Signal_1/// \brief 类型检查严格,一个参数的事件委托器/////////////////////////////////////////////////////////////////////////////////template <typename ReturnType, typename ParamType>class L_Signal_1 : public L_SignalRoot<ReturnType>{public: /// \brief 指定事件名,注册对应的一个参数的事件委托器。 template <typename Caller, typename Func> void MFuncRegister(Caller* pCaller, Func func) { // 指定专门处理一个参数的函数执行体 FuncCache<ReturnType> mfunc(MFuncCall_1<ReturnType, Caller, Func, ParamType>::MFuncCall); // 压入对象和函数 mfunc.Push(&pCaller, sizeof(Caller*)); mfunc.Push(&func, sizeof(Func)); // 添加到事件委托器列表 m_MemberFuncMap.insert(make_pair(pCaller, mfunc)); } /// \brief 指定事件名,调用其对应的一个参数的事件委托器。 ReturnType MFuncCall(const ParamType& data) { // 清空返回值 ReturnType result; memset(&result, 0, sizeof(result)); // 对于所有委托器,调用注册的函数 func_map::iterator it = m_MemberFuncMap.begin(); while (it != m_MemberFuncMap.end()) { result = it->second.Execute(&data); ++it; } return result; }};class EventCallerA{public: bool Do(int event_id) { printf("EventCallerA do event %d.\r\n", event_id); return true; }};class EventCallerB{public: bool Run(int event_id) { printf("EventCallerB run event %d.\r\n", event_id); return true; }};void main(){ // 申明返回值是bool类型,参数是int类型,单参数的事件器 L_Signal_1<bool, int> signal; EventCallerA callerA; EventCallerB callerB;// 注册委托器并调用事件 signal.MFuncRegister(&callerA, &EventCallerA::Do); signal.MFuncRegister(&callerB, &EventCallerB::Run); signal.MFuncCall(1);}
扩展:类的回调函数还可以使用以下方法实现。
1. 使用汇编,把回调函数的地址转换为C风格。使用这种方法用完后要转换回来,还有它没有了继承的特性。
2. 使用虚基类,在对方代码里,接收一个己方 继承这个虚基类的对象的指针。
3. 当然如果能完善上面这个实例,这种方法实现的回调函数最灵活。
- 基于泛型类模块,使类成员函数作为回调函数
- 类成员函数作为回调函数
- 类成员函数作为回调函数
- 如何使类的成员函数作为回调函数
- 如何使类的成员函数作为回调函数
- 如何使类的成员函数作为回调函数
- 如何使 类的成员函数作为回调函数
- 如何使类的成员函数作为回调函数
- 如何使 类的成员函数作为回调函数
- 如何使类的成员函数作为回调函数
- 如何使 类的成员函数作为回调函数
- 如何使 类的成员函数作为回调函数
- 将成员函数作为回调函数
- C++ 成员函数作为回调函数
- 成员函数作为回调函数
- 用类的成员函数作为窗口回调函数
- c++类成员函数作为回调函数
- 如何让类的成员函数作为回调函数
- Analyzing the Analyzers 分析分析师 —— 数据科学部门如何建
- (译)TMX地图格式
- 性能优化系列总篇
- s2sh整合(详细版)
- Hook linux 网络封包
- 基于泛型类模块,使类成员函数作为回调函数
- 黑马程序员 .NET学习笔记 <10>
- JAVA面试宝典
- Spring2.5那些事之基于AOP的方法级注解式日志配置
- UVA - 757 Gone Fishing
- WebService 之 WSDL文件 讲解
- 编程规范
- SSH 分页方法一,基于struts2
- ASM 2——raw设备绑定