Introduction
Microsoft introduced a new feature called Delegates in the .NET framework.
These are actually a class which holds a list of function pointers. As long as
they have the same function signature, the delegate object can hold static,
global or member function pointer. Now I'm going to do the same in an 'unmanaged
C++' way by using the External polymorphism pattern.
- Construct the abstract delegate base class
class Delegate {public:
virtual void Invoke()=0;
protected:
Delegate(){}
virtual ~Delegate(){}
};
- Construct a derived class which accepts a static/global function pointer
#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;
};
#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);
}
- Construct another derived class which accepts a member function pointer
#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<T>::Invoke()
{
cout << "TypeDelegate Invoke\r\n";
(m_t.*m_pfn)(m_iParam);
}
- Now glue up everything
#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;
}
- And the output is
NonTypeDelegate Invoke
Test Invoked
TypeDelegate Invoke
A::Test Invoked
Final Note
You can also 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