[comp.lang.c++] Event Handling and Classes

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