I know this has been asked so many times, and because of that it's difficult to dig through the cruft and find a simple example of what works.
I've got this, it's simple and it works for MyClass
...
#include <iostream>
using std::cout;
using std::endl;
class MyClass
{
public:
MyClass();
static void Callback(MyClass* instance, int x);
private:
int private_x;
};
class EventHandler
{
public:
void addHandler(MyClass* owner)
{
cout << "Handler added..." << endl;
//Let's pretend an event just occured
owner->Callback(owner,1);
}
};
EventHandler* handler;
MyClass::MyClass()
{
private_x = 5;
handler->addHandler(this);
}
void MyClass::Callback(MyClass* instance, int x)
{
cout << x + instance->private_x << endl;
}
int main(int argc, char** argv)
{
handler = new EventHandler();
MyClass* myClass = new MyClass();
}
class YourClass
{
public:
YourClass();
static void Callback(YourClass* instance, int x);
};
How can that be rewritten so EventHandler::addHandler()
will work with both MyClass
and YourClass
. I'm sorry but it's just the way my brain works, I need to see a simple example of what works before I can comprehend why/how it works. If you've got a favorite way to make this work now's the time to show it off, please markup that code and post it back.
[edit]
It was answered but the answer was deleted before I could give the checkmark. The answer in my case was a templated function. Changed addHandler to this...
class EventHandler
{
public:
template<typename T>
void addHandler(T* owner)
{
cout << "Handler added..." << endl;
//Let's pretend an event just occured
owner->Callback(owner,1);
}
};
What you want to do is to make an interface which handles this code and all your classes implement the interface.
Note that for this to work the "Callback" function is non static which i believe is an improvement. If you want it to be static, you need to do it as JaredC suggests with templates.
MyClass
andYourClass
could both be derived fromSomeonesClass
which has an abstract (virtual)Callback
method. YouraddHandler
would accept objects of typeSomeonesClass
andMyClass
andYourClass
can overrideCallback
to provide their specific implementation of callback behavior.Instead of having static methods and passing around a pointer to the class instance, you could use functionality in the new C++11 standard:
std::function
andstd::bind
:The
addHandler
method now accepts astd::function
argument, and this "function object" have no return value and takes an integer as argument.To bind it to a specific function, you use
std::bind
:You need to use
std::bind
when adding the handler, as you explicitly needs to specify the otherwise implicitthis
pointer as an argument. If you have a free-standing function, you don't have to usestd::bind
:Having the event handler use
std::function
objects, also makes it possible to use the new C++11 lambda functions:Here's a concise version that works with class method callbacks and with regular function callbacks. In this example, to show how parameters are handled, the callback function takes two parameters:
bool
andint
.This restricts the C++11-specific code to the addCallback method and private data in class Caller. To me, at least, this minimizes the chance of making mistakes when implementing it.
If you have callbacks with different parameters you can use templates as follows:
// compile with: g++ -std=c++11 myTemplatedCPPcallbacks.cpp -o myTemplatedCPPcallbacksApp
A complete working example from the code above.... for C++11:
Output should be: