作者:Fox
本文同时发布在http://www.yulefox.com和http://www.cppblog.com/fox。
十天之前,在CPPBLOG上写了一篇消息映射机制的简单实现,有同学提到该实现不支持成员函数。这个问题我也考虑到了,既然被提出来,不妨把实现提供出来。
需要说明的是,我本身对template比较不感冒,不过Kevin Lynx对template感冒,而且写过关于成员函数指针的问题,想了很久,如果支持成员函数指针,不用模板是不行了。
此处对成员函数的支持还不涉及对函数参数的泛化,因为我这个消息映射暂时不需要参数泛化,下面的代码应该不需要过多的解释了。
#define REG_MSG_FUNC(nMsgType, MsgFunc) \
CMsgRegister::RegisterCallFunc(nMsgType, MsgFunc);
#define REG_MSG_MEM_FUNC(nMsgType, Obj, MsgFunc) \
CMsgRegister::RegisterCallFunc(nMsgType, Obj, MsgFunc);
class CBaseMessage;
class CHandler
{
public:
virtual int operator()(CBaseMessage* pMsg) = 0;
};
template<typename FuncType>
class CDefHandler : public CHandler
{
public:
CDefHandler(){}
CDefHandler(FuncType &Func)
: m_Func(Func)
{
}
virtual int operator()(CBaseMessage* pMsg)
{
return m_Func(pMsg);
}
protected:
FuncType m_Func;
};
template<typename ObjType, typename FuncType>
class CMemHandler : public CHandler
{
public:
CMemHandler(){}
CMemHandler(ObjType* pObj, FuncType Func)
: m_pObj(pObj)
, m_Func(Func)
{
}
virtual int operator()(CBaseMessage* pMsg)
{
return (m_pObj->*m_Func)(pMsg);
}
protected:
FuncType m_Func;
ObjType* m_pObj;
};
class CFunction
{
public:
CFunction()
: m_pHandler(NULL)
{
}
// 封装(C函数或静态成员函数)
template<typename FuncType>
CFunction( FuncType &Func )
: m_pHandler(new CDefHandler<FuncType>(Func))
{
}
// 封装(非静态成员函数)
template<typename ObjType, typename FuncType>
CFunction( ObjType* pObj, FuncType Func )
: m_pHandler(new CMemHandler<ObjType, FuncType>(pObj, Func))
{
}
virtual ~CFunction()
{
DELETE_SAFE(m_pHandler);
}
// 函数调用
int operator()(CBaseMessage* pMsg)
{
return (*m_pHandler)(pMsg);
}
private:
CHandler *m_pHandler;
};
typedef std::map<int, CFunction*> MSG_MAP;
typedef MSG_MAP::iterator MSG_ITR;
class CMsgRegister
{
public:
// 注册消息函数(C函数或静态成员函数)
template <typename FuncType>
inline static void RegisterCallFunc(int nMsgType, FuncType &Func)
{
CFunction *func = new CFunction(Func);
s_MsgMap[nMsgType] = func;
}
// 注册消息函数(非静态成员函数)
template <typename ObjType, typename FuncType>
inline static void RegisterCallFunc(int nMsgType, ObjType* pObj, FuncType Func)
{
CFunction *func = new CFunction(pObj, Func);
s_MsgMap[nMsgType] = func;
}
// 执行消息
inline static void RunCallFunc(int nMsgType, CBaseMessage* pMsg)
{
MSG_ITR itr = s_MsgMap.find(nMsgType);
if( s_MsgMap.end() != itr )
{
(*itr->second)(pMsg);
}
}
static void ReleaseMsgMap() // 释放消息映射表
{
MSG_ITR itr = s_MsgMap.begin();
while( itr != s_MsgMap.end() )
{
DELETE_SAFE(itr->second);
itr = s_MsgMap.erase(itr);
}
}
protected:
static MSG_MAP s_MsgMap; // 消息映射表
};
不可否认,模板给了你更大的想象空间,很多东西,还是不要一味排斥的好:)。