DELEGATES and C++

Environment: [eg VC6 SP4, W98 W2K NT ...]

Presentation:

This article shows an implementation of delegates. What is a delegate? An object that acts like a multi-function pointer with a subscription system. It really simplifies the use of static or 'object' member function pointers for callback notifications and event handling. While implementation is a bit complicated, the use is very intuitive:
Quick Sample:

class CFoo {
public:

   // declaration of member callback
   void Foo( int );

};

// declaration of static callback
void Foo( int i );


void main( ) {

   CFoo obj;

   ...

   // Declare a delegate for functions
   // with one argument of type int
   CDelegate1< int > delegate;

   // Add Foo static function
   delegate.Add( Foo );
   // Add Foo member function based on foo object
   delegate.Add( obj, CFoo::Foo );

   ...

   // Execute the callbacks
   delegate( 0 );

   ...

   // Remove Foo static function
   delegate.Remove( Foo );
   // Remove Foo member function
   delegate.Remove( obj, CFoo::Foo );

}

How to?

You just have to add the headers to your project and include the "Delegates.h" header in your C++ code (in stdafx.h for example) to gain access to these classes:

No Multi-Threading Multi-Threading (with MFC)
No argument
CDelegate0
CMTDelegate0
1 argument
CDelegate1< ARG >
CMTDelegate1< ARG >
2 arguments
CDelegate2< ARG1, ARG2 >
CMTDelegate2< ARG2, ARG2 >



Notes:

a) STL is used for multi-platform implementation.
b) C++ does not authorize variable length template argument lists and that's why I made different implementations for delegates with zero, one or two arguments. If someone knows how to do in another way, just let me know.
c) C++ only defines scope resolution operator for base classes. We have to specify the conversion in this particular case:
class CFoo
{
   ...
   void Foo( int ) { }
   ...
   void Init( CDelegate1& delegate )
   {
      // ERROR: CFoo:: operator does not exist here
      delegate.Add( *this, CFoo::Foo );

      // CORRECT: type cast is available
      delegate.Add( *this, (void (CFoo::* )( int )) Foo );
   }
   ...
};
To solve this little "read/write complication" we can define a typedef in our class declaration:
class CFoo
{
   ...
   typedef MEMBER_FUNCTION_CALL_TYPEDEF1( CFoo, int ) OwnHandler;
   ...
};

So we could have:
delegate.Add( *this, (OwnHandler) Foo );

Actually the 'base' macros are:
MEMBER_FUNCTION_CALL_TYPEDEF0 for 0 arg member function
MEMBER_FUNCTION_CALL_TYPEDEF1 for 1 arg member function
MEMBER_FUNCTION_CALL_TYPEDEF2 for 2 args member function

You could also define a macro with MEMBER_FUNCTION_CALLx in your cpp file...

Conclusion:

I hope this code will help you in your programming. I'm working at EOLE SA and this method helped me in my work because it's lighter and less restrictive than interface definition/derivation style of notifications (connection points).
Thanks for your attention. Please report any bugs!

Downloads

Download source and samples - 43 Kb
Download source only- 11 KB Kb


Comments

  • Small bug

    Posted by Legacy on 09/04/2001 12:00am

    Originally posted by: robo

    in Delegate2.h at line 383 is this:
    
    

    protected:
    ARG1& m_arg1;
    ARG1& m_arg2;

    which of course should be:

    protected:
    ARG1& m_arg1;
    ARG2& m_arg2;


    Reply
  • Excellent..Maitre..just what I needed.

    Posted by Legacy on 06/11/2001 12:00am

    Originally posted by: Salomon Moyal-Bloch

    It's exactly what I need for a few projects..

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

Top White Papers and Webcasts

  • With 81% of employees using their phones at work, companies have stopped asking: "Is corporate data leaking from personal devices?" and started asking: "How do we effectively prevent corporate data from leaking from personal devices?" The answer has not been simple. ZixOne raises the bar on BYOD security by not allowing email data to reside on the device. In addition, Zix allows employees to maintain complete control of their personal device, therefore satisfying privacy demands of valued employees and the …

  • Managing your company's financials is the backbone of your business and is vital to the long-term health and viability of your company. To continue applying the necessary financial rigor to support rapid growth, the accounting department needs the right tools to most efficiently do their job. Read this white paper to understand the 10 essentials of a complete financial management system and how the right solution can help you keep up with the rapidly changing business world.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds