- 论坛徽章:
- 0
|
我写了一套宏用来支持类似于C#的delegate功能 源代码如下
#include <vector>;
class AutoPtrBase
{
protected:
class CRegCut
{
public:
inline int GetRefCount()
{
return m_nRef;
}
inline void UnRef()
{
m_nRef --;
}
inline void Ref()
{
m_nRef ++;
}
virtual ~CRegCut()
{
}
CRegCut()
{
m_nRef = 0;
}
private:
friend class AutoPtrBase;
int m_nRef;
};
protected:
AutoPtrBase(){}
inline CRegCut * GetRegCut()
{
return m_pRegCut;
}
CRegCut * m_pRegCut;
};
template<class T>;
class CMyAutoPtr : public AutoPtrBase
{
public:
/* CMyAutoPtr<T>;& operator=(CMyAutoPtr<T>;& rhs)
{
if ( rhs.m_pRegCut != 0 )
rhs.m_pRegCut->;Ref();
Release();
m_pData = rhs.m_pData;
m_pRegCut = rhs.m_pRegCut;
return *this;
}*/
template<class T2>;
CMyAutoPtr<T>;& operator=(const CMyAutoPtr<T2>;& rhs)
{
if ( rhs.GetRegCut() != 0 )
rhs.GetRegCut()->;Ref();
Release();
m_pData = (T*)rhs.get();
m_pRegCut = rhs.GetRegCut();
return *this;
}
CMyAutoPtr()
{
m_pData = 0;
m_pRegCut = 0;
}
CMyAutoPtr(T* pT)
{
m_pData = 0;
m_pRegCut = 0;
if ( pT != 0 )
{
m_pRegCut = new CRegCut();
m_pRegCut->;Ref();
m_pData = pT;
}
}
template<class T2>;
CMyAutoPtr(const CMyAutoPtr<T2>;& rhs)
{
if ( rhs.GetRegCut() != 0 )
rhs.GetRegCut()->;Ref();
m_pData = (T*)rhs->;get();
m_pRegCut = rhs.GetRegCut();
}
CMyAutoPtr(const CMyAutoPtr<T>;& rhs)
{
if ( rhs.m_pRegCut != 0 )
rhs.m_pRegCut->;Ref();
m_pData = rhs.m_pData;
m_pRegCut = rhs.m_pRegCut;
}
virtual ~CMyAutoPtr()
{
Release();
}
T* operator->;()
{
return get();
}
friend BOOL operator==(const void * pSor1 , const CMyAutoPtr<T>;& ptrSor2);
friend BOOL operator==(const CMyAutoPtr<T>;& ptrSor1 , const void * pSor2);
template<class T2>;
friend BOOL operator==(const CMyAutoPtr<T>;& ptrSor1 , const CMyAutoPtr<T2>;& ptrSor2);
friend BOOL operator!=(const void * pSor1 , const CMyAutoPtr<T>;& ptrSor2);
friend BOOL operator!=(const CMyAutoPtr<T>;& ptrSor1 , const void * pSor2);
template<class T2>;
friend BOOL operator!=(const CMyAutoPtr<T>;& ptrSor1 , const CMyAutoPtr<T2>;& ptrSor2);
T& operator*()
{
return *get();
}
void Release()
{
if ( m_pRegCut != 0 )
{
m_pRegCut->;UnRef();
if ( m_pRegCut->;GetRefCount() == 0 )
{
delete m_pRegCut;
m_pRegCut = 0;
delete m_pData;
m_pData = 0;
}
}
}
T* get() const
{
return m_pData;
}
private:
T * m_pData;
};
template<class T>;
BOOL operator==(const void * pSor1 , const CMyAutoPtr<T>;& ptrSor2)
{
return pSor1 == ptrSor2.get();
}
template<class T>;
BOOL operator==(const CMyAutoPtr<T>;& ptrSor1 , const void * pSor2)
{
return pSor2 == ptrSor1.get();
}
template<class T , class T2>;
BOOL operator==(const CMyAutoPtr<T>;& ptrSor1 , const CMyAutoPtr<T2>;& ptrSor2)
{
return ptrSor1.get() == ptrSor2.get();
}
template<class T>;
BOOL operator!=(const void * pSor1 , const CMyAutoPtr<T>;& ptrSor2)
{
return pSor1 != ptrSor2.get();
}
template<class T>;
BOOL operator!=(const CMyAutoPtr<T>;& ptrSor1 , const void * pSor2)
{
return pSor2 != ptrSor1.get();
}
template<class T , class T2>;
BOOL operator!=(const CMyAutoPtr<T>;& ptrSor1 , const CMyAutoPtr<T2>;& ptrSor2)
{
return ptrSor1.get() != ptrSor2.get();
}
//这以上部分是个智能指针 下面要用的
#define DEFCMDCLASS0(Name,Action,Execute) \
class Name##IMyCmd\
{ \
public: \
virtual void Excute##Action = 0;\
virtual ~##Name##IMyCmd(){};\
virtual BOOL IsSame(##Name##IMyCmd * pCmd) = 0;\
};\
template<class T>;\
class Name##CMyCmd : public Name##IMyCmd\
{\
public:\
typedef void (T::*Act)##Action##;\
\
Name##CMyCmd(T * pT , Act action) :\
m_pT(pT) , m_action(action)\
{\
}\
virtual ~##Name##CMyCmd()\
{\
}\
public: \
virtual void Excute##Action##\
{\
(m_pT->;*m_action)##Execute##;\
}\
virtual BOOL IsSame(##Name##IMyCmd * pCmd)\
{\
Name##CMyCmd<T>; * pConv = (Name##CMyCmd<T>; *)pCmd;\
if ( pConv->;m_pT != m_pT ) return FALSE;\
if ( pConv->;m_action != m_action ) return FALSE;\
return TRUE;\
}\
private: \
T * m_pT;\
Act m_action;\
};\
typedef CMyAutoPtr<##Name##IMyCmd>; Name##IMyCmdPtr;\
class Name##CCmdInclude\
{\
public:\
Name##CCmdInclude()\
{\
}\
virtual ~##Name##CCmdInclude()\
{\
}\
void AddCmd(Name##IMyCmdPtr pCmd)\
{\
if ( pCmd != 0)\
m_cmdList.push_back(pCmd);\
}\
void Excute##Action##\
{\
cmdVector::size_type nSize = m_cmdList.size();\
if ( nSize == 0 ) return;\
Name##IMyCmdPtr * pcmdList = new Name##IMyCmdPtr[nSize];\
for( int i = 0 ; i < nSize ; i ++ )\
pcmdList = m_cmdList;\
for( i = 0 ; i < nSize ; i ++ )\
pcmdList->;Excute##Execute##;\
delete[] pcmdList;\
}\
void DelCmd(Name##IMyCmdPtr pCmd)\
{\
cmdVector::iterator i = m_cmdList.begin();\
for( ; i < m_cmdList.end() ; i ++ )\
{\
if ( (*i)->;IsSame(pCmd.get()) )\
{\
m_cmdList.erase(i);\
return;\
}\
}\
}\
void ClearAllCmd()\
{\
m_cmdList.erase(m_cmdList.begin(),m_cmdList.end());\
}\
private:\
typedef std::vector<##Name##IMyCmdPtr>; cmdVector;\
std::vector<##Name##IMyCmdPtr>; m_cmdList;\
};
#define DEFCMDCLASS(Name,Action,Execute) \
class Name##IMyCmd\
{ \
public: \
virtual void Excute##Action = 0;\
virtual ~##Name##IMyCmd(){};\
};\
template<class T>;\
class Name##CMyCmd : public Name##IMyCmd\
{\
public:\
typedef void (T::*Act)##Action##;\
\
Name##CMyCmd(T * pT , Act action) :\
m_pT(pT) , m_action(action)\
{\
}\
virtual ~##Name##CMyCmd()\
{\
}\
public: \
virtual void Excute##Action##\
{\
(m_pT->;*m_action)##Execute##;\
}\
private: \
T * m_pT;\
Act m_action;\
};\
typedef CMyAutoPtr<##Name##IMyCmd>; Name##IMyCmdPtr;\
class Name##CCmdInclude\
{\
public:\
Name##CCmdInclude()\
{\
m_pCmd = 0;\
}\
virtual ~##Name##CCmdInclude()\
{\
m_pCmd = 0;\
}\
void SetCmd(##Name##IMyCmdPtr pCmd)\
{\
m_pCmd = pCmd;\
}\
void Excute##Action##\
{\
if ( m_pCmd != 0 )\
m_pCmd->;Excute##Execute##;\
}\
private:\
Name##IMyCmdPtr m_pCmd;\
};
#define DEFCMDCLASS2(Name,RetType,Action,Execute) \
class Name##IMyCmd\
{ \
public: \
virtual RetType Excute##Action = 0;\
virtual ~##Name##IMyCmd(){};\
};\
template<class T>;\
class Name##CMyCmd : public Name##IMyCmd\
{\
public:\
typedef RetType (T::*Act)##Action##;\
\
Name##CMyCmd(T * pT , Act action) :\
m_pT(pT) , m_action(action)\
{\
}\
virtual ~##Name##CMyCmd()\
{\
}\
public: \
virtual RetType Excute##Action##\
{\
return (m_pT->;*m_action)##Execute##;\
}\
private: \
T * m_pT;\
Act m_action;\
};\
typedef CMyAutoPtr<##Name##IMyCmd>; Name##IMyCmdPtr;\
class Name##CCmdInclude\
{\
public:\
Name##CCmdInclude()\
{\
m_pCmd = 0;\
}\
virtual ~##Name##CCmdInclude()\
{\
m_pCmd = 0;\
}\
void SetCmd(##Name##IMyCmdPtr pCmd)\
{\
m_pCmd = pCmd;\
}\
RetType Excute##Action##\
{\
ASSERT( m_pCmd != 0 );\
return m_pCmd->;Excute##Execute##;\
}\
private:\
Name##IMyCmdPtr m_pCmd;\
};
#define CMDPTR(Name) Name##IMyCmdPtr
#define TYPECMDPTR(Name) typedef CMyAutoPtr<##Name##IMyCmd>;
#define CMDINCLUDE(Name) Name##CCmdInclude
#define CMD(Name) Name##IMyCmd *
#define NEWCMDPTR(Name,Type,InstPtr,Action) new Name##CMyCmd<##Type##>;(##InstPtr##,##Type##::##Action##)
#define NEWCMDPTR0(Name,Type,Action) new Name##CMyCmd<##Type##>;(this,##Type##::##Action##)
以上的代码需要stl类库的支持 共定义了9个宏,大致用法如下:
DEFCMDCLASS DEFCMDCLASS0 DEFCMDCLASS2三个宏是delegate的定义宏 其中DEFCMDCLASS支持普通的没有返回值的delegate的定义,DEFCMDCLASS2支持又返回值得定义 DEFCMDCLASS0支持了类似于C#中的event的功能,宏的参数格式如下:Name是delegate的名称 要求唯一,
Action是delegate函数的定义,Execute是执行这个定义函数的代码,(就是把函数的参数逐一列出来),比如:DEFCMDCLASS(myCmd,(int * nVal,double * dbVal),(nVal,dbVal))。注意,Action和Execute必须用括号括起来,DEFCMDCLASS2中的 RetType 是返回类型
CMDINCLUDE 就是delegate的事例定义 如CMDINCLUDE(myCmd) m_onCmd;
CMDINCLUDE定义的类的的分两种情况:第一种是用DEFCMDCLASS0定义的 那么这个类有AddCmd,DelCmd,Excute和ClearAllCmd 而其他的CMDINCLUDE只支持SetCmd和Excute方法
NEWCMDPTR和NEWCMDPTR0两个宏是用来给Cmd赋值的 其中Name就是delegate的名字,Type是相应delegate的函数所在的类的名字,而InstPtr是指向这个类的指针,Action是相应函数的名字 比如m_onCmd.SetCmd(NEWCMDPTR(myCmd,MyClass,this,OnCmd)) NEWCMDPTR0默认用this代替了InstPtr
举个完整的例子:
class MyClass;
DEFCMDCLASS(MyCmd,(MyClass * pParam),(pParam))
class MyClass
{
...
CMDINCLUDE(MyCmd) m_onEvent;
void XX()
{
...
m_onEvent.Excute(this); //这里面填写的就是delegate定义的格式
}
};
class Another
{
...
MyClass m_myClass;
Another()
{
...
m_myClass.SetCmd(NEWCMDPTR0(MyCmd,Another,OnMyClassEvent));
}
...
void OnMyClassEvent(MyClass * pClass)
{
... //这样在m_myClass调用XX()时就会自动调用this->;OnMyClassEvent()了
}
}; |
|