Click here to Skip to main content
Click here to Skip to main content

An event mechanism for C++ using an interface based delegate

, 29 Mar 2007
Rate this:
Please Sign up or sign in to vote.
Introducing a simple event mechanism for C++ using a C# style delegate.

Introduction

This article introduces a very simple and comfortable event mechanism in C++. In many cases, a delegate in C++ is hard to understand because of its complexity. The attached code is a sample that uses the combination of the C# delegation style and Java's inner class callback style. It can show you an example of an easy event mechanism.

Event Processing

// delegate
struct ISampleEventHandler : public IEventHandler
{
    virtual void callback( IUnknown* object, const SampleEventArgs& e ) = 0;
    typedef SampleEventArgs _EventArgs; // passive polymorphism using typedef
};

// event
template<typename T>
class Event
{
public:
    void invoke(IUnknown* object, const EventArgs& e = EventArgs::Empty)
    {
        std::set<T*>::iterator iter;
        for (iter = m_EventHandler.begin();
            iter != m_EventHandler.end();
            ++iter)
        {
            // this code can promise the type-safe callback because
            // of the polymorphism using typedef in delegate
            (*iter)->callback(object, static_cast<const T::_EventArgs&>(e));
        }
    }
    void operator+=(T* eventHandler)
    {
        m_EventHandler.insert(eventHandler);
    }

    void operator-=(T* eventHandler)
    {
        m_EventHandler.erase(eventHandler);
    }

protected:
    std::set<T*> m_EventHandler;
};

Using the Code

We need an abstract parent class to identify the event sender.

class IUnknown
{
public:
 virtual ~IUnknown() {}
 virtual std::string name() = 0;
};

Here is the event sending class:

class Callee : public IUnknown
{
public:
// declare the event.
 Event<ISampleEventHandler> SampleEvent;
public:
 void test()
 {
  SampleEventArgs e;
  e.sampleData = 10;
  e.sampleData2 = 20;

// event occur.
  SampleEvent.invoke(this, e);
 }
 std::string name() { return "callee"; }
};

Here is the event receiving class:

class Caller : public IUnknown
{
public:
 Caller()
 {
// register Caller's inner class object to Callee.
  m_Callee.SampleEvent += &sampleEventHandler;
 }
 ~Caller()
 {
// unregister Caller's inner class object from Callee.
  m_Callee.SampleEvent -= &sampleEventHandler;
 }
 void test()
 {
  m_Callee.test();
 }
private:
 void print(IUnknown* object, const SampleEventArgs& e)
 {
  std::cout << object->name().c_str() << std::endl;
  std::cout << e.sampleData << std::endl;
  std::cout << e.sampleData2 << std::endl;
 }
 std::string name() { return "caller"; }
private:
 class SampleEventHandler : public ISampleEventHandler
 {
  void callback( IUnknown* object, const SampleEventArgs& e )
  {
    // to access outer class's member function.
    Caller* outer = reinterpret_cast<Caller*>((char*)this - 
                       offsetof(Caller, sampleEventHandler));

    outer->print(object, e);
  }
 } sampleEventHandler;
private:
 Callee m_Callee;
};

Points of Interest

You can easily find the reason why using the delegate is nice. It can break the cyclic dependency of each class - the 'Caller' depends on the 'Callee' but the 'Callee' does not have dependency with any classes.

History

  • 2007. 03. 29 - Initially released.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

choiday

Korea (Republic Of) Korea (Republic Of)
No Biography provided

Comments and Discussions

 
Questionstd::set ?!? Pinmemberemilio_grv31-Mar-07 3:28 
AnswerRe: std::set ?!? Pinmemberchoiday31-Mar-07 5:25 
GeneralSome Suggestions PinmemberStuart Dootson29-Mar-07 23:13 
GeneralRe: Some Suggestions Pinmemberchoiday30-Mar-07 14:57 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140814.1 | Last Updated 29 Mar 2007
Article Copyright 2007 by choiday
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid