3

Hey i'm trying to make a very simple GUI using SFML, and i want to be able to attach a function to my Button class in the constructor, as so the user can define what happens when the button is pressed.

I've worked a little before with GLUT and noticed these declerations:

glutReshapeFunc(Resize);
glutDisplayFunc(Draw);

Which apparently define what function should be called when the window is resized or displayed. I want something exactly like this for my button so upon construction you can define what function should be called. I want to be able to pass a function name just like glut, not having define a new class wich overides a virtual functin.

  • I also doubt it's possible however to pass parameters for these called functions, as you never know what or how many there would be. Am i right?

So anyway..... How do i accomplish this or something like it?? Thanks!

Griffin
  • 2,399
  • 7
  • 48
  • 83
  • 1
    GLUT is entirely C, no C++. You can download the source code to "freeglut" to see how it's done there, it just stores a couple function pointers that you pass it. – Dietrich Epp Jul 25 '11 at 04:32

3 Answers3

2

You can store a callback using e.g. std::function (for C++0x; boost::function is also available and has a similar interface).

#include <functional>

class Button {
public:
    template<typename T>
    explicit
    Button(T const& t): callback(t) {}

    void
    press()
    {
        callback();
    }

private:
    std::function<void()> callback;
};

// example use with a lambda
Button b([] { do_stuff(); });
b.press(); // will call do_stuff
Luc Danton
  • 34,649
  • 6
  • 70
  • 114
  • how exactly, in a VERY quick explination, does boost accomplish this? eg: through virtual functions? – Griffin Jul 25 '11 at 04:34
  • @Griffin Using virtual functions is a possibility but not the only way to do it. The technique is called type-erasure and [here are some techniques](http://stackoverflow.com/questions/5450159/type-erasure-techniques) for it. With that said, I'd advise not reinventing `std::function`. It's okay to try it once for learning though. – Luc Danton Jul 25 '11 at 04:36
1

In C++ it's better to use virtual function approach to address such kind of problems. That's more maintainable at long run.

You can choose to redesign a little bit to your code, where you can have a common handle to various subclasses. Now based on subclass chosen you can call a particular function. For example:

class Shape
{
public:
  virtual void Resize () = 0;
  virtual void Draw () = 0;
};

class Triangle : public Shape
{
public:
//  implement above to functions
};

class Square : public Shape
{
public:
//  implement above to functions
};

Now, just pass the handle of Shape* wherever you want and call the above abstract methods;

void foo(Shape *p)
{
  p->Resize();
}
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • Haha, we programmers probably need to move on from these old shape + animals examples for OOP. :) – hugomg Jul 25 '11 at 04:20
  • yeah this is one way, but do you have any knowledge on how glut does it? here you have to define a whole new class, using glut you just need to pass the name of a defined function. How do i do this? – Griffin Jul 25 '11 at 04:25
  • @Griffin, no idea about that. May be you can edit your question to give minimal code example that what you want exactly. – iammilind Jul 25 '11 at 04:26
  • 1
    @missingo how about car... What else hasn't been used... Oh yea! Person. – Tom Fobear Jul 25 '11 at 06:25
0

(Rewrote everything), I had misread the question.

You seem to be wanting to pass plain old function pointers around to other functions. All you need to do is just pass the name of the function you want, but do so inside an if (or something like that) so the function passed is actualy what you want:

if(i am feeling lucky today){
    glutDisplayFunc(DrawMyLuckyShape);
}else{
    glutDisplayFunc(DrawAFoo);
}

The bad news is that since C is a nasty language you can't set up to pass extra parameters to your functions (ie, use closures). Therefore, you need to rely on a) the functions being passed some parameter quen being called or b) the functions looking at some global state.

hugomg
  • 68,213
  • 24
  • 160
  • 246
  • yeah this is one way, but do you have any knowledge on how glut does it? here you have to define a whole new class, using glut you just need to pass the name of a defined function. How do i do this? – Griffin Jul 25 '11 at 04:28
  • Forget about classes, just realized glut is plain old C apparently. Mostly bad news, therefore - what are you trying to do, more specifically? – hugomg Jul 25 '11 at 04:42