Search code examples
c++callbacksignals-slots

In c++ is there any Events/delegates/interfaces/notifications! anything?


Say i have these classes ViewA and ViewB

In objective C using the delegate pattern I could do

@protocol ViewBDelegate{

- (void) doSomething();
}

then in ViewB interface:

id<ViewBDelegate> delegate;

then in ViewA implementation i set the delegate:

viewB.delegate = self;

and now I can call in doSomething from viewB onto any that unknown type delegate.

[delegate doSomething];

"C++ How to Program" has been the worse read an can't find simple examples that demonstrates basic design patterns.

What i'm looking for in C++ is:

  • events ActionScript and java
  • or delegates or NSNotifications in Objective C

anything that allows class A, Class B and Class C to know that ClassX didSomething()!!!

thanks


Solution

  • If I were you, I wouldn't use function pointers to accomplish this task. Leave this option to the gurus ;)

    In Boost, there is a beautiful library called signals. It makes your life easier! This is an example of usage:

    #include <iostream>
    #include <boost/bind.hpp>
    #include <boost/signal.hpp>
    using namespace std;
    using namespace boost;
    
    struct A
    {   void A_action() { cout << "A::A_action();" << endl; }   };
    struct B
    {   void B_action() { cout << "B::B_action();" << endl; }   };
    struct C
    {   void C_action() { cout << "C::C_action();" << endl; }   };
    struct X
    {
        // Put all the functions you want to notify!
        signal<void()> list_of_actions;
        void do_something()
        {
            std::cout << "Hello I am X!" << endl;
            list_of_actions(); // send notifications to all functions in the list!
        }
    };
    int main()
    {
        X x;
        A a;
        B b;
        C c;
        x.list_of_actions.connect(bind(&A::A_action, a));
        x.list_of_actions.connect(bind(&B::B_action, b));
        x.list_of_actions.connect(bind(&C::C_action, c));
        x.do_something();
    }
    

    This will print:

    Hello I am X!
    A::A_action();
    B::B_action();
    C::C_action();
    

    Here is how it works.

    First, you declare the place that holds the delegates:

    signal<void()> list_of_actions;
    

    Then, you "connect" it to what ever group of functions/functors/callable things you want to call.

    x.list_of_actions.connect(bind(&A::A_action, a));
    x.list_of_actions.connect(bind(&B::B_action, b));
    x.list_of_actions.connect(bind(&C::C_action, c));
    

    Note, that I have used bind. So, that the type of functions in the list_of_actions is the same, but we can connect it to different type of classes. So:

    bind(&A::A_action, a)
    

    This thing, produces a callable thing, of type void () as we declared the type of list_of actions earlier. Of course, you specify the instance you want to apply this member function on in the second parameter..

    If you are doing multi-threaded stuff, then use its sister signals2.

    Hope that helps.