tohaz
tohaz

Reputation: 197

Is this the correct way to implement custom event handlers?

I was looking for a way of adding custom event handlers as a c++ class member function. Found that this code actually works. I need to separate library class and user code, allowing user code to customize library class. Here is concept of code. Is it correct to do so? Thread safeness is out of scope in my question. Compiler is gcc. User code is very very neat. no inheritance, virtual functions, templates used

#include <stdio.h>

typedef void fn();

class aaa
{
  public:
  aaa() : customhandler(NULL) {}
  fn *customhandler;
};

// user code start

void dostuff() {
  printf("doing stuff 1\n");
}
void dostuff2() {
  printf("doing stuff 2\n");
}
int main()
{
  aaa aaa1;
  aaa1.customhandler = &dostuff;
  aaa1.customhandler();
  aaa1.customhandler = &dostuff2;
  aaa1.customhandler();
}

Upvotes: 1

Views: 334

Answers (2)

C.J.
C.J.

Reputation: 16091

I tried your code and it works fine. Just for your information, there is another way to code your function pointer. In which case your code can be simplified just a little. Here I use a slightly different syntax for the typdef for the function pointer, which lets you drop the & symbols.

#include "stdafx.h"
#include <stdio.h>

typedef void (*fn)();

class aaa
{
public:
    aaa() : customhandler(NULL) {}
    fn customhandler;
};

void dostuff() {
    printf("doing stuff 1\n");
}
void dostuff2() {
    printf("doing stuff 2\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
    aaa aaa1;
    aaa1.customhandler = dostuff;
    aaa1.customhandler();
    aaa1.customhandler = dostuff2;
    aaa1.customhandler();
    return 0;
}

Both ways are just fine, I just thought I'd show you another way to do this.

Upvotes: 1

user405725
user405725

Reputation:

Well, if you had a Boost libraries or C++0x-enabled compiler, you could have had a code like this:

#include <cstdio>
#include <functional>

struct Foo
{
    std::function<void ()> handler;

    void invoke ()
    {
        if (handler)
        {
            handler ();
        }
        else
        {
            printf ("Oops, handler is not there!\n");
        }
    }
};

static void myHandler1 (int arg)
{
    printf ("Handler #1 (arg=%d)\n", arg);
}

static void myHandler2 ()
{
    printf ("Handler #2\n");
}

int main ()
{
    Foo f;

    f.invoke ();

    f.handler = std::bind (&myHandler1, 13);
    f.invoke ();

    f.handler = &myHandler2;
    f.invoke ();
}

The nice thing about it is that you can have functions or functors bound to a handler with optional additional arguments.

Your original code will also work, but what if I want to invoke a class's method and not a plain function? What if I want to also pass some state that I can access inside the handler when it is invoked? That's one of the many reasons why std::function made it into the C++ standard.

Upvotes: 2

Related Questions