This topic is 1980 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I have a base class for a messaging system (pause, unpause, key state change, pointer state change, etc.) that does not provide "handler" functionality. By this I mean that it does not provide functionality to translate, say, Win32 messages received via a window procedure into internal message types. I am currently working on extending this class with a Win32 specific implementation (basically simply writing the window procedure atop the messaging class) but am running into the following problem:

Given the base class declaration of:

 virtual inline void* getHandler() const = 0; 

I can't declare an override that returns a function pointer:

 typedef LRESULT(CALLBACK WinProc)(HWND, UINT, WPARAM, LPARAM); virtual inline WinProc* getHandler() const; 

Because the overridden return type "... is not identical to nor covariant with the return type "void *"..."

I've been considering two alternatives:

1) Functor return type for both:

 typedef LRESULT(CALLBACK WinProc)(HWND, UINT, WPARAM, LPARAM); struct BaseFunctor {}; virtual inline BaseFunctor* getHandler() const = 0; struct Win32Functor : public BaseFunctor { WinProc* handler; LRESULT CALLBACK operator()(HWND window, UINT msg, WPARAM wp, LPARAM lp) { handler(window, msg, wp, lp); } }; virtual inline Win32Functor* getHandler() const; 

2) Fun with reinterpret_cast:

 virtual inline void* getHandler() const { return reinterpret_cast<void*>(&handler); } //Later... typedef LRESULT(CALLBACK WinProc)(HWND, UINT, WPARAM, LPARAM); WinProc* wp = reinterpret_cast<WinProc*>(messenger->getHandler()); wp(window, msg, wp, lp); 

My question is threefold: Is there a way to resolve this more clearly? Which of the above two (or the TBD three) methods is generally better, or does it make any difference? Is there away to resolve it with function pointers as in the original code? Edited by greenvertex

Share on other sites
Void pointers generally be avoided.

Your callback functions almost certainly have a common signature. Specify that signature as a base or specify a template that describes that signature as your return type.

For example:
[source lang="cpp"]typedef void(*HandlerFunction)(HWND, UINT, WPARAM, LPARAM);

HandlerFunction GetHandler()
{ ... }[/source]
With that your function can return a known function pointer instead of a raw void pointer. Edited by frob

Share on other sites
Your callback functions almost certainly have a common signature.[/quote]

I generally don't know the signature of the function to be called in the base class, thus the need for some generic initial return type for getHandler(). For example, some other environment might not use something akin to a windows procedure to manage events and may involve a more traditional event system. In which case, the signature of this method would most likely look completely different (i.e. accepting some generalized event data struct). I would only know the signature in the specialization of the base class (Win32 version for example has a well-defined function signature for message handling).

Maybe this is just code smell and I should add an option: Defining a function signature that takes some generalized data struct to translate into internal messages.

 enum MessageType {MT_SYSTEM, MT_KEY, MT_POINTER}; struct GenericMessage { MessageType type; unsigned char target; //Some unique id (i.e. ASCII value for keys) unsigned x; unsigned y; //... }; typedef void(MessageHandler)(const GenericMessage&); inline virtual MessageHandler* getHandler() const; 

However this sort of shifts responsibility for translating messages into GenericMessage types to subclasses of my window class. Whereas what I was trying for would basically plug a specific message handler type into a specific window type through a factory class. Or not, and the user could roll their own system using the standard implementation for that context - window procedures for example is the standard way in which messages are handled in Win32. I short, I don't necessarily want the interdependence between these classes...