信号槽的实现并不复杂,如果了解观察者模式加上标准模板去实现并不难,方法也很多,我现在提供一种现实方法,供参考(版权所有,引用请说明出处)。
头文件:
call.h
//////////////////
#pragma once
#include <vector>
using namespace std;
template<class RT>
class ReturnType
{
public:
typedef RT T;
};
//////////////////////////////////////////////////////////////////////////
//to take the right work for 64 bit data pointers
class CallID
{
public:
CallID();
CallID(void* pObject, void* pPfn);
CallID(const CallID& rSrc);
virtual void operator=(const CallID& rSrc);
virtual bool operator==(const CallID& rSrc) const;
virtual bool operator!=(const CallID& rSrc) const;
protected:
void* m_pObject,
* m_pPfn;
};
//////////////////////////////////////////////////////////////////////////
//ICallHandleImp Declaration
class ICallHandleImp
{
public:
//operator
static void* operator new(size_t nSize);
static void operator delete(void* p);
protected:
//operator
ICallHandleImp &operator= (const ICallHandleImp&);
};
//////////////////////////////////////////////////////////////////////////
//CallHandleImp<ICALLSTUB> Declaration
template<class ICALLSTUB>
class CallHandleImp :public ICallHandleImp
{
public:
//Status
CallID GetID()const;
//Implementation
ICALLSTUB* Attch(ICALLSTUB* pCallStub);
void Detach();
long GetRef() const;//*m_pCallStub's reference count.
protected:
//construction/destruction
CallHandleImp(ICALLSTUB* pCallStub);
//SmartPtr<ICALLSTUB> m_pCallStub;
ICALLSTUB* m_pCallStub;
};
//Declaration and Implementation of the helper class-template Equal ID cmd.
template<typename Handle>
class EqualIdCmd
{
public:
EqualIdCmd(CallID nID):m_nID(nID){};
~EqualIdCmd(){};
bool operator()(void* pVoid)
{
Handle* pCH = (Handle*)pVoid;
return (pCH->GetID() == m_nID);
}
private:
CallID m_nID;
};
//////////////////////////////////////////////////////////////////////////
//EventImp Declaration
template<class CALLHANDLE>
class EventImp
{
public:
const CALLHANDLE& SetWatch(const CALLHANDLE& rCallHandle);
bool RemoveWatch(const CALLHANDLE& rCallHandle);
bool RemoveWatch(const CallID& rCallID);
void RemoveAll();
bool IsEmpty() const;
protected:
EventImp();
EventImp(const EventImp& rEventImp);
~EventImp();
//operators
EventImp& operator =(const EventImp& rEventImp);
//Attributes
std::vector<CALLHANDLE* > m_rgpCallHandles;
};
//////////////////////////////////////////////////////////////////////////
//ICallStubImp Declaration
class ICallStubImp
{
public:
//status
virtual CallID GetID() const = 0;
//Implementation
long GetRef() const;
long AddRef();
long Release();
protected:
ICallStubImp();
ICallStubImp(const ICallStubImp& rCallStubImp);
virtual ~ICallStubImp();
ICallStubImp& operator =(const ICallStubImp& rCallStubImp);
private:
// attributes
long m_lRefCount;
};
//////////////////////////////////////////////////////////////////////////
// ICallStub0< RT> Declaration
template<class RT>
class ICallStub0 : public ICallStubImp
{
public:
typedef typename ReturnType<RT>::T Ret_t;
virtual Ret_t operator()() const = 0;
};
//////////////////////////////////////////////////////////////////////////
// ICallStub1< RT> Declaration
template<class RT, class AT1>
class ICallStub1 : public ICallStubImp
{
public:
typedef typename ReturnType<RT>::T Ret_t;
virtual Ret_t operator()(AT1 agr1) const = 0;
};
//////////////////////////////////////////////////////////////////////////
//CallStubImp<ICALSTUB, CALL> Declaration
template<class ICALLSTUB, class CALL >
class CallStubImp : public ICALLSTUB
{
public:
//status
virtual CallID GetID() const;
protected:
CallStubImp(const CALL& rCall);
//attributes
CALL m_Call;
};
//////////////////////////////////////////////////////////////////////////
//CallStub1 < RT, AT1, CALL1 > Declaration
template<class RT, class AT1, class CALL1 >
class CallStub1 : public CallStubImp< ICallStub1 < RT, AT1>, CALL1 >
{
public:
CallStub1(const CALL1& rCall);
//operators
typedef typename ReturnType<RT>::T Ret_t;
virtual Ret_t operator()(AT1 arg1) const;
};
//////////////////////////////////////////////////////////////////////////
//FunctionImp Declaration
template<class FUNCTION_PTR>
class FunctionImp
{
public:
CallID GetID() const;
protected:
//type
typedef FUNCTION_PTR FUNCTION_PTR;
FunctionImp(FUNCTION_PTR pfn);
//attributes
FUNCTION_PTR m_pfn;
};
//////////////////////////////////////////////////////////////////////////
//function1 declaration
template<class RT, class AT1>
class Function1 : public FunctionImp< RT(*)(AT1) >
{
public:
Function1(FUNCTION_PTR pfn);
//operators
typedef typename ReturnType<RT>::T Ret_t;
Ret_t operator()(AT1 arg1) const;
};
//////////////////////////////////////////////////////////////////////////
//MethodImp Declaration
template<class CLASS, class METHOD_PTR>
class MethodImp
{
public:
//status
CallID GetID() const;
protected:
//type
typedef METHOD_PTR METHOD_PTR;
MethodImp(CLASS* pObject, METHOD_PTR pmfn);
//attributes
CLASS* m_pObject;
METHOD_PTR m_pmfn;
};
//////////////////////////////////////////////////////////////////////////
//IgnoreImp Declaration
template<class CALL>
class IgnoreImp
{
public:
//status
CallID GetID() const;
protected:
IgnoreImp(const CALL& rCall);
//attributes
CALL m_Call;
};
//////////////////////////////////////////////////////////////////////////
//Ignore1Stof1 Declaration
template<class RT, class AT1, class CALL0>
class Ignore1Stof1 : public IgnoreImp< CALL0>
{
public:
Ignore1Stof1(const CALL0& rCall0);
//operators
typedef typename ReturnType<RT>::T Ret_t;
Ret_t operator ()(AT1 arg1) const;
};
//////////////////////////////////////////////////////////////////////////
//Method1 Declaration
template<class RT, class CLASS, class AT1>
class Method1 : public MethodImp <CLASS, RT(CLASS::*)(AT1) >
{
public:
Method1(CLASS* pObject, METHOD_PTR pmfn);
//operators
typedef typename ReturnType<RT>::T Ret_t;
Ret_t operator ()(AT1 arg1) const;
};
//////////////////////////////////////////////////////////////////////////
//CallHandle1<RT, AT1> Declaration
template<class RT, class AT1>
class CallHandle1 : public CallHandleImp< ICallStub1<RT, AT1>>
{
public:
CallHandle1(ICallStub1<RT, AT1>* pCallStub = nullptr);
//operators
typedef typename ReturnType<RT>::T Ret_t;
Ret_t operator ()(AT1 arg1) const;
};
//////////////////////////////////////////////////////////////////////////
//Event1 Declaration
template<class AT1>
class Event1 : public EventImp< CallHandle1< void, AT1> >
{
public:
//operators
void operator ()(AT1 arg1) const;
};
//////////////////////////////////////////////////////////////////////////
//Several Helper Macros and Functions
#define CALL_INTERFACE_DECL_0( RT )const ICallStub0< RT >*
#define CALL_INTERFACE_DECL_1( RT, AT1 )const ICallStub1< RT, AT1 >*
#define CALL_INTERFACE_DECL_2( RT, AT1, AT2 )const ICallStub2< RT, AT1, AT2 >*
#define CALL_INTERFACE_DECL_3( RT, AT1, AT2, AT3 )const ICallStub3< RT, AT1, AT2, AT3 >*
#define CALL_INTERFACE_0( RT )( ( const ICallStub0< RT >*) nullptr)
#define CALL_INTERFACE_1( RT, AT1 )( ( const ICallStub1< RT, AT1 >*) nullptr )
#define CALL_INTERFACE_2( RT, AT1, AT2 )( ( const ICallStub2< RT, AT1, AT2 >*) nullptr)
#define CALL_INTERFACE_3( RT, AT1, AT2, AT3 )( ( const ICallStub3< RT, AT1, AT2, AT3 >*) nullptr )
#define Function( pfn )__Function(pfn)
#define Method( pObject, pmfn)__Method(pObject, pmfn)
#define MakeFunction0Function
#define MakeFunction1Function
#define MakeFunction2Function
#define MakeFunction3Function
#define MakeMethod0Method
#define MakeMethod1Method
#define MakeMethod2Method
#define MakeMethod3Method
#define BindFirst__BindFirst( rCall, rArg, GetCallInterface( rCall))
#define BindSecond__BindSecond( rCall, rArg, GetCallInterface( rCall))
#define BindThird__BindThird( rCall, rArg, GetCallInterface( rCall))
#define ConverRetVal( rCall, rConverter)__ConverRetval( rCall, rConverter, GetCallInterface( rCall), GetCallInterface( rConverter))
#define ConverFirst( rCall, rConverter)__ConverFirst( rCall, rConverter, GetCallInterface( rCall), GetCallInterface( rConverter))
#define ConverSecond( rCall, rConverter)__ConverSecond( rCall, rConverter, GetCallInterface( rCall), GetCallInterface( rConverter))
#define ConverThird( rCall, rConverter)__ConverThird( rCall, rConverter, GetCallInterface( rCall), GetCallInterface( rConverter))
#define Expression( rCall0)__Expression(rCall0, GetCallInterface( rCall0))
#include "call.inl"
//////////////////call.inl////////////////////////////////
#include "call.h"
#include <algorithm>
//////////////////////////////////////////////////////////////////////////
//CallStubImp<ICALLSTUB, CALL> Implementation
template<class ICALLSTUB, class CALL >
inline CallStubImp< ICALLSTUB, CALL>::CallStubImp(const CALL& rCall)
:m_Call(rCall)
{
}
//status
template<class ICALLSTUB, class CALL >
inline CallID CallStubImp< ICALLSTUB, CALL>::GetID() const
{
return m_Call.GetID();
}
//////////////////////////////////////////////////////////////////////////
//CallStub1<RT, AT1, CALL1> Implementation
template<class RT, class AT1, class CALL1>
inline CallStub1<RT, AT1, CALL1>::CallStub1(const CALL1& rCall1)
:CallStubImp< ICallStub1< RT, AT1>, CALL1 >(rCall1)
{
}
//operators
template<class RT, class AT1, class CALL1>
inline typename ReturnType<RT>::T CallStub1< RT, AT1, CALL1>::operator()(AT1 arg1) const
{
return m_Call(arg1);
}
//////////////////////////////////////////////////////////////////////////
//EventImp Implementation
template< class CALLHANDLE >
inline EventImp< CALLHANDLE>::EventImp()
{
}
template< class CALLHANDLE >
inline EventImp< CALLHANDLE>::EventImp(const EventImp&)
{
}
template< class CALLHANDLE >
inline EventImp< CALLHANDLE>::~EventImp()
{
RemoveAll();
}
//operators
template< class CALLHANDLE >
inline EventImp< CALLHANDLE>& EventImp <CALLHANDLE>::operator =(const EventImp&)
{
return *this;
}
//Implementation
template< class CALLHANDLE >
inline const CALLHANDLE& EventImp< CALLHANDLE>::SetWatch(const CALLHANDLE& rCallHandle)
{
CALLHANDLE* pNew = new CALLHANDLE(rCallHandle);
m_rgpCallHandles.push_back(pNew);
return *pNew;
}
template< class CALLHANDLE >
inline bool EventImp< CALLHANDLE>::RemoveWatch(const CALLHANDLE& rCallHandle)
{
return RemoveWatch(rCallHandle.GetID());
}
template< class CALLHANDLE >
inline bool EventImp< CALLHANDLE>::RemoveWatch(const CallID& rCallID)
{
std::vector< CALLHANDLE*>::iterator end = m_rgpCallHandles.end();
EqualIdCmd<CALLHANDLE> cmd(rCallID);
std::vector<CALLHANDLE*>::iterator iter = std::find(m_rgpCallHandles.begin(), end, cmd);
if (iter != end)
{
CALLHANDLE* pCH = *iter;
m_rgpCallHandles.erase(iter);
delete pCH;
return true;
}
return false;
}
template< class CALLHANDLE >
inline void EventImp< CALLHANDLE>::RemoveAll()
{
int nSize = (int)m_rgpCallHandles.size();
for (int i = 0; i < nSize; ++i)
{
delete m_rgpCallHandles[i];
}
m_rgpCallHandles.clear();
}
template< class CALLHANDLE >
inline bool EventImp< CALLHANDLE>::IsEmpty() const
{
return m_rgpCallHandles.size() == 0;
}
template< class CALLHANDLE >
void CopyCallIDs(const std::vector<CALLHANDLE*>& m_rgpCallHandles, std::vector< CallID>& rgpCallIDs)
{
rgpCallIDs.reserve(m_rgpCallHandles.size());
std::vector< CALLHANDLE*>::const_iterator iter = m_rgpCallHandles.begin();
std::vector< CALLHANDLE*>::const_iterator end = m_rgpCallHandles.end();
for (; iter != end; ++iter)
{
CALLHANDLE* pCH = *iter;
rgpCallIDs.push_back(pCH->GetID());
}
}
//////////////////////////////////////////////////////////////////////////
//MethodImp Implementation
template< class CLASS, class METHOD_PTR >
inline MethodImp< CLASS, METHOD_PTR>::MethodImp(CLASS* pObject, METHOD_PTR pmfn)
:m_pObject(pObject)
,m_pmfn(pmfn)
{
}
//status
template < class CLASS, class METHOD_PTR >
inline CallID MethodImp< CLASS, METHOD_PTR>::GetID() const
{
return CallID((void*)m_pObject, *((void**)&m_pmfn));
}
//////////////////////////////////////////////////////////////////////////
//Method Implementation
template<class RT, class CLASS, class AT1 >
inline Method1<RT, CLASS, AT1 >::Method1(CLASS* pObject, METHOD_PTR pmfn)
:MethodImp< CLASS, METHOD_PTR>(pObject, pmfn)
{
}
#pragma warning(push)
#pragma warning(disable : 4701)
//operators
template<class RT, class CLASS, class AT1 >
inline typename ReturnType<RT>::T Method1< RT, CLASS, AT1>::operator()(AT1 arg1) const
{
typedef ReturnType<RT>::T(CLASS::*Method)(AT1);
return (m_pObject->*((Method)m_pmfn))(arg1);
}
#pragma warning( pop)
//////////////////////////////////////////////////////////////////////////
//IgnoreImp Implementation
template< class CALL >
inline IgnoreImp< CALL >::IgnoreImp(const CALL& rCall)
:m_Call(rc)
{
}
//status
template< class CALL >
inline CallID IgnoreImp< CALL >::GetID() const
{
return m_Call.GetID();
}
//////////////////////////////////////////////////////////////////////////
//CallHandleImp< ICALLSTUB > Implementation
template<class ICALLSTUB >
inline CallHandleImp< ICALLSTUB>::CallHandleImp(ICALLSTUB* pCallStub)
:m_pCallStub(pCallStub)
{
}
//status
template<class ICALLSTUB >
inline CallID CallHandleImp< ICALLSTUB >::GetID() const
{
return m_pCallStub->GetID();
}
//Implementation
template<class ICALLSTUB >
inline ICALLSTUB* CallHandleImp< ICALLSTUB >::Attch(ICALLSTUB* pCallStub)
{
m_pCallStub = pCallStub;
return pCallStub;
}
template<class ICALLSTUB >
inline void CallHandleImp< ICALLSTUB >::Detach()
{
m_pCallStub = nullptr;
}
template<class ICALLSTUB >
inline long CallHandleImp< ICALLSTUB >::GetRef() const
{
if (m_pCallStub == nullptr)
{
return 0;
}
return m_pCallStub->GetRef();
}
//////////////////////////////////////////////////////////////////////////
//CallHandle1< RT, AT1 > Implementation
template< class RT, class AT1 >
inline CallHandle1< RT, AT1>::CallHandle1(ICallStub1 <RT, AT1>* pCallStub)
:CallHandleImp< ICallStub1< RT, AT1 > >(pCallStub)
{
}
//operators
template< class RT, class AT1>
inline typename ReturnType<RT>::T CallHandle1< RT, AT1 >::operator()(AT1 arg1) const
{
return (*m_pCallStub)(arg1);
}
//////////////////////////////////////////////////////////////////////////
//Event1 Implementation
//operators
template<class AT1>
inline void Event1< AT1 >::operator()(AT1 arg1) const
{
typedef CallHandle1< void, AT1 > CALLHANDLE;
if (!m_rgpCallHandles.empty())
{
//create snapshot of call-ids
std::vector< CallID> rgpCallIDs;
CopyCallIDs<CALLHANDLE>(m_rgpCallHandles, rgpCallIDs);
//notify
for (std::vector<CallID>::size_type i = 0; i < rgpCallIDs.size(); i++)
{
std::vector<CALLHANDLE*> ::const_iterator end = m_rgpCallHandles.end();
EqualIdCmd< CALLHANDLE > cmd(rgpCallIDs[i]);
std::vector< CALLHANDLE*>::const_iterator iter = std::find_if(m_rgpCallHandles.begin(), end, cmd);
if (iter != end)
{
CALLHANDLE* pCH = *iter;
(*pCH)(arg1);
}
}
}
}
//////////////////////////////////////////////////////////////////////////
//Determining Call-Interface
void GetCallInterface();
//function1
template< class RT, class AT1 >
inline CALL_INTERFACE_DECL_1(RT, AT1) GetCallInterface(const Function1< RT,AT1>& )
{
return nullptr;
}
//Method1
template< class RT, class CLASS, class AT1 >
inline CALL_INTERFACE_DECL_1(RT, AT1) GetCallInterface(const Method1< RT, CLASS, AT1 >&)
{
return nullptr;
}
//////////////////////////////////////////////////////////////////////////
//CallStub Helpers Impleemntation
void __CreateCallStub();
//Call0 -> CallStub1
template< class CALL0, class RT, class CS_RT, class CS_AT1 >
inline CallStub1< CS_RT, CS_AT1,
Ignore1Stof1< CS_RT, CS_AT1, CALL0 > >* __CreateCallStub(const CALL0& rCall0,
CALL_INTERFACE_DECL_1(CS_RT, CS_AT1),
CALL_INTERFACE_DECL_0(RT))
{
typedef Ignore1Stof1< CS_RT, CS_AT1, CALL0> CALL1;
typedef CallStub1 <CS_RT, CS_AT1, CALL1 > CALLSTUB1;
return new CALLSTUB1(CALL1(rCall0));
}
//Call1->CallStub1
template< class CALL1, class RT, class AT1, class CS_RT, class CS_AT1 >
inline CallStub1< CS_RT, CS_AT1, CALL1 >* __CreateCallStub(const CALL1& rCall1,
CALL_INTERFACE_DECL_1(CS_RT, CS_AT1),
CALL_INTERFACE_DECL_1(RT, AT1))
{
typedef CallStub1< CS_RT, CS_AT1, CALL1> CALLSTUB1;
return new CALLSTUB1(rCall1);
}
//////////////////////////////////////////////////////////////////////////
//Determining CreateCallStub-Interface
void CreateCallStub();
//Any Call->CallStub1
template< class CALL, class RT, class AT1>
inline ICallStub1< RT, AT1 >* CreateCallStub(const CALL& rCall,
CALL_INTERFACE_DECL_1(RT, AT1) CallStubInterface)
{
return __CreateCallStub(rCall, CallStubInterface, GetCallInterface(rCall));
}
//////////////////////////////////////////////////////////////////////////
//CallHandle Helpers Implementation
void CreateCallHandle();
//Any Call->CallHandle1
template< class CALL, class RT, class AT1>
inline CallHandle1< RT, AT1 > CreateCallHandle(const CALL& rCall,
CALL_INTERFACE_DECL_1(RT, AT1) CallHandleInterface)
{
return CreateCallStub(rCall, CallHandleInterface);
}
//////////////////////////////////////////////////////////////////////////
//SetWatch/RemoveWatch Implementation
template< class AT1, class CALL>
inline const CallHandle1< void, AT1 >& SetWatch(Event1< AT1 >& rEvent1, const CALL& rCall)
{
return rEvent1.SetWatch(CreateCallHandle(rCall, CALL_INTERFACE_1(void, AT1)));
}
template<class EVENT, class CALL >
inline bool RemoveWatch(EVENT& rEvent, const CALL& rCall)
{
return rEvent.RemoveWatch(rCall.GetID());
}
void __Function();
template< class RT, class AT1 >
inline Function1<RT, AT1> __Function(RT(*pfn)(AT1))
{
return pfn;
}
void __Method();
template< class RT, class METHOD_CLASS, class AT1, class OBJECT_CLASS >
inline Method1< RT, METHOD_CLASS, AT1 > __Method(OBJECT_CLASS* pObject,
RT(METHOD_CLASS::*pmfn)(AT1) const)
{
typedef RT(METHOD_CLASS::*NonConstMethod)(AT1);
return Method1< RT, METHOD_CLASS, AT1 >(pObject, (NonConstMethod)pmfn);
}
template< class RT, class METHOD_CLASS, class AT1, class OBJECT_CLASS >
inline Method1< RT, METHOD_CLASS, AT1 > __Method(OBJECT_CLASS* pObject, RT(METHOD_CLASS::*pmfn)(AT1))
{
return Method1<RT, METHOD_CLASS, AT1 >(pObject, pmfn);
}
///////////////////////////call.cpp///////////////////////////////////////////
#include "stdafx.h"
#include "call.h"
#include <wtypes.h>
//////////////////////////////////////////////////////////////////////////
//Due to the lack of an __int64 data type we need a class CallID
CallID::CallID()
:m_pObject(nullptr)
,m_pPfn(nullptr)
{
}
CallID::CallID(void* pObject, void* pPfn)
:m_pObject(pObject)
,m_pPfn(pPfn)
{
}
CallID::CallID(const CallID& rSrc)
:m_pObject(rSrc.m_pObject)
,m_pPfn(rSrc.m_pPfn)
{
}
void CallID::operator=(const CallID& rSrc)
{
m_pObject = rSrc.m_pObject;
m_pPfn = rSrc.m_pPfn;
}
bool CallID::operator==(const CallID& rSrc) const
{
if (m_pObject != rSrc.m_pObject)
return false;
if (m_pPfn != rSrc.m_pPfn)
return false;
return true;
}
bool CallID::operator!=(const CallID& rSrc) const
{
if (m_pObject != rSrc.m_pObject)
return true;
if (m_pPfn != rSrc.m_pPfn)
return true;
return false;
}
//////////////////////////////////////////////////////////////////////////
//ICallStubImp Implementation
ICallStubImp::ICallStubImp()
:m_lRefCount(0)
{
}
ICallStubImp::ICallStubImp(const ICallStubImp& )
:m_lRefCount(0)
{
}
ICallStubImp::~ICallStubImp()
{
}
//Implementation
long ICallStubImp::GetRef() const
{
return m_lRefCount;
}
long ICallStubImp::AddRef()
{
return ++m_lRefCount;
}
long ICallStubImp::Release()
{
long lRefCount = --m_lRefCount;
if (lRefCount < 0)
{
delete this;
}
return lRefCount;
}
//////////////////////////////////////////////////////////////////////////
//ICallHandleImp Implementation
void* ICallHandleImp::operator new(size_t nSize)
{
return ::operator new(nSize);
}
void ICallHandleImp::operator delete(void* p)
{
::operator delete(p);
}
ICallHandleImp& ICallHandleImp::operator =(const ICallHandleImp& )
{
return *this;
}
///////////////////////////////测试////////////////////////////////////
// SetWatch.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "call.h"
class Action
{
public:
Action(){}
~Action(){}
void MyAction()
{
m_Event(10);
}
public:
Event1<int> m_Event;
};
class Response
{
public:
Response(Action* pAct)
:m_pAct(pAct)
{
SetWatch(m_pAct->m_Event, MakeMethod1(this, &Response::ShowInfo));
}
~Response(){};
public:
void ShowInfo(int nData)
{
printf("call ShowInfo nData = %d", nData);
}
private:
Action* m_pAct;
};
int _tmain(int argc, _TCHAR* argv[])
{
Action act;
Response res(&act);
act.MyAction();
getchar();
return 0;
}
代码很多,以后有时间会多加点注释和分析。