Set a class instance's function after it has already been defined
I am trying to give a class event functions such as .onShow() and .onHide(), so when the object is shown, the .onShow() function will run. How can I allow the function to be change like so:
MyClass myInst = MyClass();
my开发者_StackOverflow社区Inst.onShow = OnShowFunction;
Is it possible to allow this?
You can use function pointers or std::function
(also in BOOST) to achieve this. However, it looks like you might be trying to adopt a javascript or scripting-language programming style in C++ - I'd warn against that, you should change your programming style depending on how it fits the language. A typical alternative in C++ is to have onShow
a virtual method that can be overriden by derivatives.
You probably do not want to dynamically change the function at runtime, If you do then one of the other answers will show you how to use functors. But to me it sounds like you want different objects to have different functionality based on some property of the object.
This is what virtual function are for:
You define the action in the base class. Then in a derived class you give the actual implementation based on how the object is meant to act.
class MyClass
{
public:
virtual void onShow() = 0;
};
class Window: public MyClass
{
public:
virtual void onShow() { /* Draw Window */ }
};
void aboutToShowObject(MyClass& obj)
{
obj.onShow();
}
This is how you do it (and impress/horrify your cow-orkers at the same time):
#include <iostream>
class MyClass
{
public:
void (MyClass::*OnShow)() ;
void OnShowFunction() ;
} ;
int main (int argc, char** argv)
{
MyClass C ;
C.OnShow = MyClass::OnShowFunction ;
(C.*C.OnShow)() ;
}
void MyClass::OnShowFunction()
{
std::cout << "void MyClass::OnShowFunction()\n" ;
}
Yes, this is possible.
You need to use a function pointer or a wrapper that encapsulates function pointers and other callable objects, like function
, which can be found in various forms in C++0x, C++ TR1, and Boost.
Depending on how you are using the callbacks, a signals library like Boost.Signals might be more elegant.
You can use std::function which is a wrapper class that will let you assign functors as well as C functions in a safe way.
However using a functor Hierarchy here is a very straightforward solution.
class Object
{
BaseOnShow& onShow;
}
class onShow1 : BaseOnShow { ... };
class onShow2 : BaseOnShow { ... };
...
Object obj;
onShow1 OnShowFunction; // careful about the lifetime of this one
obj.onShow = OnShowFunction;
Then, as usual, specific functionalities of onShow must be used through virtual function members.
If you want to dynamically change the function pointer at runtime, you could keep the function pointer as a member, and use a default method called OnShow() that calls the function pointer:
#include <iostream>
using namespace std;
void OnShow() {
cout << "Showing!" << endl;
}
typedef void(*EventProc)();
class Widget {
private:
EventProc m_ep;
public:
Widget() : m_ep(0) {}
void SetOnShow(EventProc ep) {m_ep = ep;}
void OnShow() {(*m_ep)();}
};
int main() {
Widget w;
w.SetOnShow(::OnShow);
w.OnShow();
return 0;
}
精彩评论