DELEGATES and C++
|
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( CDelegate1To solve this little "read/write complication" we can define a typedef in our class declaration:& 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 ); } ... };
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 KbDownload source only- 11 KB Kb
|
Partners
More for Developers
Top Authors
- Voted: 13 times.
- Voted: 11 times.
- Voted: 11 times.
- Voted: 10 times.
- Voted: 8 times.
- Paul Kimmel 78 articles
- Tom Archer - MSFT 75 articles
- Zafir Anjum 61 articles
- Bradley Jones 43 articles
- Marius Bancila 31 articles