1. Construct the abstract delegate base class
class Delegate {public: virtual void Invoke()=0;protected: Delegate(){} virtual ~Delegate(){}};
2. Construct a derive class which accepts a static/global function pointer
//NonTypeDelegate.h#include "Delegate.h"class NonTypeDelegate : public Delegate{public: void Invoke(); NonTypeDelegate(void (*pfn)(int),int iParam); virtual ~NonTypeDelegate(){}private: void (*m_pfn)(int); int m_iParam;};//NonTypeDelegate.cpp#include "NonTypeDelegate.h"#include <iostream>using namespace std;NonTypeDelegate::NonTypeDelegate(void (*pfn)(int), int iParam):m_pfn(pfn), m_iParam(iParam){}void NonTypeDelegate::Invoke(){ cout << "NonTypeDelegate Invoke\r\n"; m_pfn(m_iParam);}
3. Construct another derive class which accepts a member function pointer
//TypeDelegate.hpp#include "Delegate.h"#include <iostream>using namespace std;template <typename T>class TypeDelegate : public Delegate{public: void Invoke(); TypeDelegate(T &t, void (T::*pfn)(int), int iParam); ~TypeDelegate(){}private: T m_t; void (T::*m_pfn)(int); int m_iParam;};template<typename T>TypeDelegate<T>::TypeDelegate(T &t, void (T::*pfn)(int), int iParam):m_t(t), m_pfn(pfn), m_iParam(iParam){}template<typename T>void TypeDelegate<T7gt;::Invoke(){ cout << "TypeDelegate Invoke\r\n"; (m_t.*m_pfn)(m_iParam);}
4. Now glue up all the stuffs
#include <iostream>#include "NonTypeDelegate.h"#include "TypeDelegate.hpp"#include <vector>using namespace std;void Test(int iParam){ cout << "Test Invoked\r\n";}class A{ public: void Test(int iParam) { cout << "A::Test Invoked\r\n"; }};int main(int argc, char* argv[]){ NonTypeDelegate nTDelegate(Test,1); A a; TypeDelegate<A> tDelegate(a,A::Test,2); vector<Delegate*> vecpDelegate; vecpDelegate.push_back(&nTDelegate); vecpDelegate.push_back(&tDelegate); for (vector<Delegate*>::const_iterator kItr=vecpDelegate.begin(); kItr!=vecpDelegate.end(); ++kItr) { (*kItr)->Invoke(); } return 0;}
5. And the output is
NonTypeDelegate InvokeTest InvokedTypeDelegate InvokeA::Test Invoked
Actually, you can derive a class which can accept different signature of functions pointer. Thanks to the powerful "external polymorphism" pattern.
References Chris Cleeland, Douglas C.Schmidt and Timothy H.Harrison External Polymorphism : An Object Structural Pattern for Transparently Extending C++ Concrete Data Types
Chris Cleeland, Douglas C.Schmidt and Timothy H.Harrison External Polymorphism : An Object Structural Pattern for Transparently Extending C++ Concrete Data Types