Subscribe a button to trigger some function dynamically in C++?
I'm trying to make a button class (abstract) so I can set what function is that button going to trigger when clicked dynamically when my program load.
I want to construct all my buttons by reading XML files, this is to avoid code replication so having only 1 "generic" button class is really useful for me.
I was wondering if you could dynamically pass the necessary information about a method, like a pointer to the method's owner and method in question name, or even better the direct pointer to the method, for a button to call 开发者_开发百科that function/method when clicked ?
Since pointer to function is a runtime artifact you cannot store that in the offline configuration. I see two solutions that might fit what you describe:
- put your functions into a dynamic library and load them by name - that way your configuration would map a button to library path/function name pair,
- build a "registry" of named function pointers at startup, probably some hash table, so the configuration would map a button to the hash key.
From experience though I would say that building such facilities are usually overkill, and the configuration quickly becomes heavier then the app itself.
Some additional pointers: Boost.Signals, QT Signals, Command and Chain of Responsibility design patterns.
You can create a SetFunctor
method in your generic Button
class, which accepts a function object as a parameter. Then you create a Call
method that calls the function wrapped inside the function object. Something like this:
template<typename FUNC>
class Functor
{
typedef FUNC (*FC)();
FC func;
public:
Functor( FC f ) : func(f) {}
~Functor() {}
FUNC Call() { return func(); }
FUNC operator()() const { return Call(); }
};
class Button
{
std::auto_ptr<Functor<void> > pfunc;
public:
Button() {}
~Button() {}
void SetFunctor( void(*fc)() )
{
pfunc.reset( new Functor<void>( fc ) ); // now owns ptr;
}
void Call()
{
pfunc->Call();
}
};
...
void changeColor()
{
// do work
}
Button obj;
obj.SetFunctor( changeColor );
obj.Call();
Of course I could've used better smart pointers and or better techniques, but this should give you a gist of what I was hinting at. Also note, that this Functor object can only accept functions that have no parameters. You can change this to your liking. I hope it helps!
UPDATE: A few fixes added. Sorry about that!
You are looking for the signal/slot pattern.
In C++ two popular options are boost signals and sigc.
There are a couple of ways to link a button to a function in C++ - you can use function pointers (which are somewhat scary), or a signals and slots pattern which provides the functionality of function pointer with more type safety.
As far as wiring up the function pointers or signals and slots at run time based on a config file, to do this elegantly will require reflection, which C++ doesn't provide for you. I suspect this will be the ugly part.
精彩评论