User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

    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


    IT Offers


    Top Authors