我前面写过的一篇 C++模拟C#事件机制 中给出了一个C++ event完整实现, 但是存在好多问题,主要是:由于使用静态变量存储函数类别导致不能保存多个相同函数特征(参数列表和返回值)的函数。这个重构版本充分利用了面向对象的思想,利用派生和多态封装了全局函数,成员函数,函数对象,使3者借口完全一致.
- template<class TReturn, class TArgument>
- class BaseInvoker
- {
- public:
- BaseInvoker(){}
- virtual ~BaseInvoker(){}
- public:
- virtual TReturn invoke(TArgument args) = 0;
- };
- template<class TReturn, class TArgument>
- class GlobalInvoker : public BaseInvoker<TReturn, TArgument>
- {
- public:
- typedef TReturn (*Method)(TArgument args);
- public:
- GlobalInvoker(Method pCallback)
- :mCallback(pCallback)
- {
- }
- virtual TReturn invoke(TArgument args)
- {
- return mCallback(args);
- }
- private:
- Method mCallback;
- };
- template<class TObject, class TReturn, class TArgument>
- class MemberInvoker : public BaseInvoker<TReturn, TArgument>
- {
- public:
- typedef TReturn (TObject::*MemberMethod)(TArgument);
- public:
- MemberInvoker(TObject* pObject,MemberMethod pCallback)
- :mObject(pObject), mCallback(pCallback)
- {
- }
- virtual TReturn invoke(TArgument args)
- {
- return (mObject->*mCallback)(args);
- }
- private:
- TObject* mObject;
- MemberMethod mCallback;
- };
- template<class TFunctor, class TReturn, class TArgument>
- class FunctorInvoker : public BaseInvoker<TReturn, TArgument>
- {
- public:
- typedef TFunctor* FunctorMethod;
- public:
- FunctorInvoker(FunctorMethod pCallback)
- :mCallback(pCallback)
- {
- }
- virtual TReturn invoke(TArgument args)
- {
- return mCallback(args);
- }
- private:
- FunctorMethod mCallback;
- };
delegate使用智能指针shared_ptr存储实际的函数类型(智能指针可以自己实现,也可以用boost::shared_ptr, std::tr1::shread_ptr,我这里使用的是OGRE自带的一个只能指针,其实自己写也不难),以确保安全性,相应的,delagate构造函数也要改一下:
- template<class TReturn, class TArgument>
- class Delegate
- {
- public:
- virtual ~Delegate()
- {
- }
- public:
- template<class TReturn, class TArgument>
- friend bool operator==(Delegate<TReturn, TArgument> const& lhs, Delegate<TReturn, TArgument> const& rhs);
- // for global or static methods
- Delegate(TReturn (*pCallback)(TArgument))
- :mInvoker(new GlobalInvoker<TReturn, TArgument>(pCallback))
- {
- }
- // for object member methods
- template<class TObject>
- Delegate(TObject* pObject, TReturn (TObject::*pCallback)(TArgument))
- :mInvoker(new MemberInvoker<TObject,TReturn,TArgument>(pObject,pCallback))
- {
- }
- // for functor methods
- template<class TFunctor>
- Delegate(TFunctor* pCallback)
- :mInvoker(new FunctorInvoker<TFunctor,TReturn,TArgument>(pCallback))
- {
- }
- TReturn operator() (TArgument args)
- {
- return mInvoker->invoke(args);
- }
- //implementations
- private:
- Ogre::SharedPtr<BaseInvoker<TReturn, TArgument> > mInvoker;
- // unsigned int mReference;
- };
delegate对外接口没有改变因此event及使用event的代码 无需改变,这也充分说明了抽象的好处:实现不论怎么变化,但接口不便。