Click here to Skip to main content
16,015,258 members
Articles / Programming Languages / C++
Article

Delegates in a standard C++ way

Rate me:
Please Sign up or sign in to vote.
3.57/5 (8 votes)
26 Jan 2002 67.1K   26   5
A method to duplicate .NET delegates in unmanaged C++ using the External polymorphism pattern.

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.

  1. Construct the abstract delegate base class
     //Delegate.h
    
    class Delegate {public:
        virtual void Invoke()=0;
    protected:
        Delegate(){}
        virtual ~Delegate(){}
    };
  2. Construct a derived 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 derived 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<T>::Invoke()
    {   
    	cout << "TypeDelegate Invoke\r\n";
    	(m_t.*m_pfn)(m_iParam);
    }
  4. 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;
    }
  5. 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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Hong Kong Hong Kong
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralTake a look at sigslot Pin
Chryler24-Feb-03 8:01
Chryler24-Feb-03 8:01 
GeneralRe: Take a look at sigslot Pin
Klaus Nowikow19-Mar-03 2:08
Klaus Nowikow19-Mar-03 2:08 
QuestionWorth it? Pin
Swinefeaster30-Jan-02 0:54
Swinefeaster30-Jan-02 0:54 
I have a large c++ project which requires a lot of delegation. First of all, there is a cModel class, which is kind of like an api to the backend, and is called by the gui classes. This cModel class needs to delegate to its correct cPage object, which in turn must delegate to its correct cElement object. So whenever I add functionality, I must add the function in all three classes to do the delegation. This kinda time consuming Frown | :(

I looked at your code, and the polymorphism pattern you mentioned, and it is an interesting idea. But it doesn't seem very practical.

1. First of all, you have to define derived class types for every single variation of your function parameter list. I don't even want to imagine what my Class View would look after this Dead | X| .

2. What if the first class (in my example, the cModel) needs to do special synchronization around the call to the lower object (cPage). Where does this code get inserted?

3. Even if you do write different classes for each possible parameter list, how do you name the variables? You would have to create even separate classes just to give the parameters in the list sensible names. And then if they are just slightly different (such as firstPageHandle versus targetPageHandle) and you want to just delegate those to each other, you would have to write separate assignment code to copy the variables over.

I appreciate you taking the time to write this article. Maybe it's only in my case that it seems hopeless... Frown | :( It would be nice if the language would support this natively somehow. (Maybe .NET does this, but I doubt it would be exactly what I need).

Cheers,

swinefeaster

Check out Aephid Photokeeper, the powerful digital
photo album solution at www.aephid.com.
AnswerWorth it? Never Pin
TW23-May-03 0:10
TW23-May-03 0:10 
GeneralRe: Worth it? Never Pin
YuetKent24-Aug-04 22:40
YuetKent24-Aug-04 22:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.