0

I have two classes. The first, called Game_Events, controls the objects and manages the general tasks. The second, called Button, is for one of those object instances.

The example below is wrong but shows how I want to do it:

class Button
{
   public:
       Button(void (*f)()) : f_m(f)
       ~Button(){}

   private:
       void (*f_m);
};

class Game_Events()
{
    public:
        Game_Events()
        {
            button = new Button(&Close);
        }
        ~Game_Events(){}
        Close(){} //I need to pass this function for call it on the other side
}

So I want to create a Button instance inside of the Game_Events class and give it authority to call the Close() function of the same class as the instance owning the button. In the tile I say "unknown function", because the function to call is to be determined when the button is constructed.

Is that possible?

  • 2
    Usually this is done by subscribing to a UI "event," in this case button.Click(). – Robert Harvey May 8 '16 at 23:17
  • 2
    Yes it is possible. How it is done depends on the language, and possibly the API you are using. – Daniel T. May 8 '16 at 23:40
5

Yes this is definitively possible.

But there are two challenges to address in your design:

  • Close() is a member function. So if the button has to call this member function, it has to know on which object to call it.

  • If later button has to action the call, you need to have it visible somehow in you rarchitecture (either it's a GUI element that performs the action when it's cliked, or it should be accessible pragrammatically inside your code.

I'll answer with C++. For the second topic, for the sake of the demo, I'll assume that button would be a public member of Game_Events.

Alternative 1: basic approach elaborating on your function pointer

If you don't need to call a member function, i.e. if Close() could be static, your code could work almost as it is, with some minor syntactic corrections:

class Button
{
   private:
       void (*f_m)();
   public:
       Button(void (*f)()) : f_m(f) {}
       ~Button(){}
       void operator() () { f_m(); }   // make button a callable (i.e. button() ) 
};

Online demo

However the use is limited, because CLose would have to be static, so it could'nt use any object dependent vvalue of the game event. What a pitty

Alternative 2: approach abstracting the function to be called

So let's make it a little bit more general. Instead of using a function pointer, or a member function pointer (which would oblige us to determine the class of the function), we could use the functional library of C++, that allows to define ab abstract function:

#include <functional>
...
class Button
{
   private:
       function<void()> f_m;
   public:
       Button(function<void()> f) : f_m(f) {}
       ~Button(){}
       void operator() () { f_m(); }
};

Then you could create a button, with total flexibility for the function that you will provide. Here I'll use a lambda function:

class Game_Events
{
    public:
        Button* button; 
        Game_Events()
        {
            button = new Button([this]()->void{this->Close(); });
        }
        ~Game_Events(){}
        void Close(){ cout<<"Boum"<<endl;} //I need to pass this function for call it on the other side
};

The requirement is that the object still exist when the button gets actioned.

online demo

Alternative 3: command design pattern

That's my favourite approach: implement the command pattern.

The general principle is slightly changed compared to your original approach, but it's easier to handle and very powerful:

  • You would have an abstract Command class with only one virtual member function: Execute().
  • Your button constructor would be constructed with a pointer to an abstract Command object (instead of a function pointer).
  • When your button is actioned, it just calls Execute() for the Command object.
  • You would have a CloseGameEvent class inheriting from Command. Its constructor would keep track of the Game_Event and its overriden Execute() would call the Close() function for it.
  • When you construct your button object, you'd then pass it the relevant CloseGameEvent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.