Delegate in Standard C++

Environment: ANSI/ISO C++

Microsoft introduced a new feature called "delegates" in the .NET framework. It is actually a class that holds a list of function pointers. As long as they own the same function signature, the delegate object can hold static, global, or member function pointers. Now I'm going to do the same in a "unmanaged C++" by way of using the "external polymorphism" pattern.

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 Invoke
Test Invoked
TypeDelegate Invoke
A::Test Invoked

Conclusion

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



Comments

  • little mistake:-)

    Posted by zhou_sqy on 12/22/2005 01:07am

    TypeDelegate tDelegate(a,A::Test,2); -------------------------------------- TypeDelegate tDelegate(a,&A::Test,2);

    Reply
  • A better approach using std C++ and boost::signal/function/bind/lambda

    Posted by Legacy on 02/23/2004 12:00am

    Originally posted by: Jeff Flinn

    See http://www.boost.org/doc/html/signals.html#id2519335, for much simpler and more complete implementation. Note that delegates as shown in Ben Chun Pong Chan's original examples are really examples of the publisher/subscriber patten.

    Also see www.boost.org for methods that are soon to be part of the next C++ standard, in particular boost::bind and boost::function. These are powerful and general utilities for dealing with functions - for those situtions not addressed by boost::signal


    Jeff

    Reply
  • And...

    Posted by Legacy on 03/14/2002 12:00am

    Originally posted by: Lorien

    How can i do a call to a func ptr of a instantiated class?

    if i have:

    class a
    {
    public:
    a() {FuncPtr = Func1;};
    a(int t)
    {
    if(t = 0) FuncPtr = Func1;
    else FuncPtr = Func2;
    };

    void Func1() {printf("Hello\n");};
    void Func2() {printf("Bye\n");};
    void (a::*FuncPtr)();
    }


    class b
    {
    public:
    b();

    a *v_a;

    void Init()
    {
    /* Anything */

    v_a = new a(1);

    /* Here i wanna call the FuncPtr member of v_a */
    /* I tried: (a->*FuncPtr)(); and more, doesn't runs */
    /* I don't want to declare FuncPtr into b */
    };
    }


    Reply
  • Great!

    Posted by Legacy on 03/03/2002 12:00am

    Originally posted by: Chen Fong

    !!

    Reply
  • lack s the .net delegate features

    Posted by Legacy on 02/17/2002 12:00am

    Originally posted by: biondello

    Interesting approach but it lacks two of .net delegates really cool features. In .Net delegates are multicast and have an invocation list to call multiple subscribers. The other one is that subscribers can be of different types. You can have instances of form1, form2 and form3 subscribe to a delegate of a button class instance and the delegate can call member functions of all the form instances. With the template approach it seems to me that you are bound to one subscriber type. Any ideas how to solve this problem?

    Reply
  • behind the curtain

    Posted by Legacy on 02/04/2002 12:00am

    Originally posted by: rb

    Very nice stuff!
    There is a view behind the curtain of C#. Now i have understood C# delegates better.

    Reply
  • Nice work. Is it possibel to deligate the method of an initiated class instanse?

    Posted by Legacy on 01/29/2002 12:00am

    Originally posted by: T. Liu

    .

    Reply
  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • A modern mobile IT strategy is no longer an option, it is an absolute business necessity. Today's most productive employees are not tied to a desk, an office, or a location. They are mobile. And your company's IT strategy has to be ready to support them with easy, reliable, 24/7 access to the business information they need, from anywhere in the world, across a broad range of communication devices. Here's how some of the nation's most progressive corporations are meeting the many needs of their mobile workers …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds