I’m trying to create an event handling system where objects can subscribe to events broadcasted by other objects and call a method when that event is broadcast. I’m trying to implement this with a singleton class called EventHandler. Objects call a public method on EventHandler that subscribes them to events broadcast by a certain object:
void startWatchingObjectEvent(PDObject * object, PDEvent event, PDObject* listener, PDReceiver receiver);
PDObject is a base class for all the objects that will be handled by the EventHandler. PDEvent is simply a unique string that identifies the Event.
PDReceiver is where I’m running into issues. I have it typedef’d to a method pointer on the PDObject class:
typedef void (PDObject::*PDReceiver)(PDObject*, PDEvent);
Now the PDObject class itself doesn’t really have any methods that EventHandler is going to call, but derived classes of PDObject will, and I wanted to create a generic type that EventHandler could store that would apply to any derived classes of PDObject. I implemented EventHandler this way and tried writing a unit test to make sure it’s working okay:
const PDEvent Test_PokeEvent = "Test_PokeEvent";
void Test_EventHandler_sendObjectMessage()
{
EventHandler& eventh = EventHandler::instance();
Test_PDObject caster;
Test_PDObject listener;
PDReceiver receiver = &Test_PDObject::test_poke;
eventh.startWatchingObjectEvent(&caster, Test_PokeEvent, &listener, (listener.*receiver)(&caster, Test_PokeEvent));
eventh.sendObjectEvent(&caster, Test_PokeEvent);
assert(listener.test_wasPoked());
}
Test_PDObject is a derived class of PDObject that just flips a wasPoked bit when test_poke is called.
The issue is that the compiler doesn’t like me trying to assign a method of Test_PDObject to the type PDReceiver since PDReceiver is defined as a method of PDObject.
Is what I’m trying to do even possible? Can I use this generic method pointer type to refer to methods of derived classes? Or is my approach just entirely flawed?
EDIT: I figured out I can use static_cast to cast the method pointer of the derived class to a method pointer of the base class like so:
PDReceiver receiver = static_cast<PDReceiver>(&Test_PDObject::test_poke);
And so far so good! My unit tests are working perfectly now.
A static_cast is indeed all that is required to cast a pointer-to-member of type
Child::*to typeBase::*, but please remember that this might be quite dangerous if you by accident use the pointer-to-member on an instance ofBase(and not the relatedChild).In the example below we use the same exact approach as described earlier, though calling
Child::funcon a object of typeBaseis causing undefined-behavior since we are accessing a non-existent member of Base inside the function.