lee@cadnetix.COM (Lee Fife) (08/29/89)
I've got a design problem I'd like to pose for the net's consideration. Consider an event processing system (No, it's not a windowing system, but that doesn't really matter) : We define an event queue class that manages all the incoming events and dispatches each event to the appropriate callback function. There are also a bunch of different classes in charge of various things which respond to different events. That is, each class has member functions which are registered with the event queue as callbacks for particular types of events. The question is: How do you design the classes implementing the callbacks so that the callbacks have a single type that can be registered with the queue manager? One Approach: Define a base class that has a callback function and derive all the event managing classes from it. E.g. enum EventType {ET1, ET2, ... }; class Event; // defined somewhere class BaseWithCallBack { private: void callback(Event *); }; class Derived : BaseWithCallBack { public: void regcallbacks(); // register all the callbacks private: void callback1(Event *); void callback2(Event *); }; // Class to manage event queue class QueueMgr { public: // register a callback for a particular event type void registercallback(EventType, void (BaseWithCallBack::*)(Event *)); void mainloop(); // get events and handle them }; Then Derived::regcallbacks() just calls QueueMgr::registercallback() for each of its callbacks. This seems ugly because there's no real connection between the base class's callback and the derived callbacks. We're using inheritance to escape type-checking, not because there's any real inheritance going on. Another Approach: Make the callbacks friends of the event managing classes. E.g. enum EventType {...}; class Event; // Class to manage event queue class QueueMgr { public: void registercallback(EventType, void (*)(Event *)); void mainloop(); // get events and handle them }; // Class to handle a set of events class HandleSomeEvents { public: void regcallbacks(); // register all the callbacks private: void friend callback1(Event *); void friend callback2(Event *); }; The problem with this approach is that the callback functions are friends functions instead of member functions and thus they don't know which instance of the HandleSomeEvents class registered them with QueueMgr. This means they can't access the data members of the registering class, which pretty much destroys the point of having classes to manage the events. What do you all think? Am I missing an obvious third alternative? Is this all screwed up? What would you do? Lee Fife Internet: lee@cadnetix.com Cadnetix Corp. UUCP: ..!{uunet,boulder}!cadnetix!lee 5775 Flatiron Pkwy. Boulder, CO 80301