tags:

views:

123

answers:

6

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();
myInst.onShow = OnShowFunction;

Is it possible to allow this?

+1  A: 

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.

James McNellis
+7  A: 

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.

AshleysBrain
+3  A: 

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();
}
Martin York
+1 and note that when Martin says that you won't change the function at runtime this way, It doesn't mean you don't have the choice of which object you want to create at runtime. You can still create one derived class or the other depending on the context. Functor or wrapper like std::function are only useful if you want to change the function during the lifetime of the object.
Ugo
A: 

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.

Ugo
Note that here the lifetime/lifecycle of onShow is different than obj's one, compared to Martin's answer.
Ugo
A: 

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" ;
  }
TonyK
Thank you TonyK, I got this to work perfectly I just made a few changes: void OnShowFunction() { /* Do Stuff */ }class MyClass {public: void (*OnShow)() ; } ;int main (int argc, char** argv) { MyClass C ; C.OnShow = OnShowFunction ; (*OnShow)() ; }
A: 

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;
}