I've built a small, limited-scope, cross-platform UI library in C++. It uses the following classes to handle UI callbacks:
// Base class for templated __Callback class to allow for passing __Callback
// objects as parameters, storing in containers, etc. (as Callback*)
class Callback
{
public:
virtual void execute() = 0;
virtual ~Callback() { }
protected:
Callback() { }
};
As the comment describes, this is the base class for callbacks - which allows for passing them as arguments and storing them inside UI widgets such that the proper callback can be executed (when, for example, a user clicks a button).
// C++ has no callbacks (in the sense of an action [method] of a
// target [object]), so we had to roll our own. This class can be used
// directly, but the NEW_CALLBACK macro is easier.
template <class __TargetType>
class __Callback : public Callback
{
public:
typedef __TargetType TargetType;
typedef void (TargetType::*ActionType)(void);
virtual void execute()
{
(this->__target->*this->__action)();
}
__Callback(TargetType* target_, ActionType action_) :
Callback(), __target(target_), __action(action_) { }
virtual ~__Callback() { }
private:
// target object for the callback
TargetType* __target;
// action (method) of the target that will be called
ActionType __action;
};
This templated class is the meat of the callback paradigm. It stores a pointer to an object and a pointer to a member function, such that the member function can be called on the target object at a later time.
#define NEW_CALLBACK(class_, obj_, act_) \
new __Callback<class_>(obj_, &class_::act_)
This macro just makes it a little easier to create a templated __Callback
object.
This has been working great for a long while! A button with a callback might be instantiated like:
MyClass* obj = new MyClass();
Button* btn = new Button("Title", NEW_CALLBACK(MyClass, obj, btnClicked));
This would create a button, to be placed in a window or other container at a later time, and when clicked it will call obj->btnClicked()
.
Now, my question (sorry for the lengthy setup, I don't think I could pare it down any more than this). A case has arisen where I need to copy a Callback*
object. Of course, since it's just a pointer to the base class, I can't determine the type of the templated derived class.
How would one go about copying an arbitrary Callback
object, with the copy pointing to the same target and action as the original? Or, is there an entirely different approach to this callback problem that I should be taking (though I would prefer not to change it too much)?
Thanks all!