I'm trying to add a simple messaging system to my project, where events can be invoked by a function, which will lead to all callbacks registered to that event being called.
Now, the logical way to do this is using function pointers. It would be easily possible to pass the pointer to the desired callback function to the events manager, for registering. An event callback function would always return an int
and take a void*
as argument.
However I don't want to register static global functions as my event callbacks - I'd like to do it with class member functions.
Is it even possible to accomplish this with C++? Storing and calling pointers to member functions of different classes but with the same function header.
If this is not possible, do you have any suggestions on how I could work around this? I'd really like to add event listeners directly to my classes.
Yes it is possible. C++0x has the function
class that handles this, and as others have pointed out Boost has similar facilities.
You can also roll your own, but the syntax is not for the faint of heart:
#include <iostream>
class Callable
{
public:
virtual ~Callable() {}
virtual int operator() (void* args) = 0;
};
class CallableFreeFunction : public Callable
{
public:
CallableFreeFunction(int (*func)(void*)) : func_(func) {}
virtual int operator() (void* args) { return (*func_)(args); }
private:
int (*func_)(void*);
};
template <typename tClass>
class ClassMemberCallable : public Callable
{
public:
ClassMemberCallable(tClass* instance, int (tClass::*memberfunction)(void*)) : instance_(instance), memberfunc_(memberfunction) {}
virtual int operator() (void* args) { return (instance_->*memberfunc_)(args); }
private:
tClass* instance_;
int (tClass::*memberfunc_)(void*);
};
class Foo
{
public:
int derp(void* args)
{
std::cout << args << '\n';
return 2;
}
};
int freefunctionfoo(void* args)
{
std::cout << "free" << args << '\n';
return 2;
}
int main(int argc, char* argv[])
{
Foo myfoo;
Callable* callable = new ClassMemberCallable<Foo>(&myfoo, &Foo::derp);
(*callable)(0);
delete callable;
callable = new CallableFreeFunction(freefunctionfoo);
(*callable)(0);
delete callable;
std::cin.get();
return 0;
}
This demonstrates a way of handling both free functions, and member functions in an opaque way. This is a simple example, and can be made more generic and robust in a number of ways. I'd refer you to these pages for syntax help:
http://www.newty.de/fpt/index.html
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
I'd also recommend looking at this for more ideas: