Sign in to follow this  
JohnHurt

functions pointers in classes

Recommended Posts

JohnHurt    334
I'm having some trouble with these things. See, I'm trying to develop a GUI system, and I need my widgets to have pointers to functions as members, so that they can execute callback functions when an event happens to them. Ok, here's my class definition:
// base class for all GUI objects
class gtGuiWidget
{
protected:
	// callback function pointer//////////
	void (*gtGuiWidget::fpLButtonDownCallback)(void);
	//////////////////////////////////////
	
	// messaging functions ///////////////
	void OnLButtonDown();
	//////////////////////////////////////
	
public:
	gtGuiWidget(void);
	virtual ~gtGuiWidget(void);
};

So whoever is using the gui would write there own callback, and send it to the class. When the widget gets an LButtonDown message, it calls this:
void gtGuiWidget::OnLButtonDown()
{
	(*gtGuiWidget::fpLButtonDownCallback)();
}

This doesn't compile, and I can't figure out the syntax to use. Anyone any ideas?

Share this post


Link to post
Share on other sites
twanvl    512
This is a pointer to a member function, you must call it using:

gtGuiWidget* myWidget;
(myWidget->*fpLButtonDownCallback)()

Share this post


Link to post
Share on other sites
JohnHurt    334
Ah yes, thank you. That works now, although I had to change it to

(*widget->fpLButtonDownCallback)();

Now, is there a way to pass a function pointer as an argument without having to declare all its own arguments, i.e.:

void SetCallBack(void (*func)(void));

The reason is that I want to be able to pass different function pointers to the same function in my widget class, so that I can set up message maps. For example.

widget->SetCallBack(on_l_button_down, L_BUTTON_DOWN);
widget->SetCallBack(on_r_button_down, R_BUTTON_DOWN);
widget->SetCallBack(on_double_click, DOUBLE_CLICK);
etc...

Not all the callbacks would have the same parameter lists.

Share this post


Link to post
Share on other sites
snk_kid    1312
First pointer to member functions != pointer to free functions

Quote:
Original post by JohnHurt

// base class for all GUI objects
class gtGuiWidget
{
protected:
// callback function pointer//////////
void (*gtGuiWidget::fpLButtonDownCallback)(void);
//...



This is incorrect syntax for pointer to member functions:


struct widget {

// typedef introduces a type alias for another type
// use it to make code clear and concise
typedef void (widget::*button_handler)();

//....

private:

button_handler b_hdler;

//....

};


Quote:
Original post by JohnHurt
That works now, although I had to change it to

(*widget->fpLButtonDownCallback)();


This is incorrect aswell but i'm not surprised as you didn't declare a pointer to a member function in the first place.

The correct syntax is:


pointers : (ptr->*mem_func_ptr)();
references : (ref.*mem_func_ptr)();


Quote:
Original post by JohnHurt
is there a way to pass a function pointer as an argument without having to declare all its own arguments, i.e.:

void SetCallBack(void (*func)(void));

The reason is that I want to be able to pass different function pointers to the same function in my widget class, so that I can set up message maps. For example. Don't nock the simple methods.

widget->SetCallBack(on_l_button_down, L_BUTTON_DOWN);
widget->SetCallBack(on_r_button_down, R_BUTTON_DOWN);
widget->SetCallBack(on_double_click, DOUBLE_CLICK);
etc...


"void (*func)(void)" declares a pointer to function which is not interchangeable with pointer to member functions, they are not equal.

You cannot declare a pointer to free/member function with-out declaring specific arguments, its the signature.

There are many ways to get round that, some of which are:

A. Probably the simplest method is to just have seperate set member function e.g. "setOnButtonDown", setDoubleClick", etc you can always add extra options to each of these. Don't knock simplicity & conciseness.

B. Your method but you have to disregard static typing. This is done by dis-regarding type altogether using the most general pointer type the void pointer (the lowest common dominator of the bunch) and using run-time type switching code or have map that maps key ids to something, when you make a match then you will have to cast the void pointer to the appropriate type. something like so:


enum cb_type { L_BUTTON_DOWN, R_BUTTON_DOWN, DOUBLE_CLICK };

void gtGuiWidget::SetCallBack(void* func, cb_type type) {

switch(type) {
case cb_type::L_BUTTON_DOWN:
// ...
break;
case cb_type::R_BUTTON_DOWN:
// ...
break;
case cb_type::DOUBLE_CLICK:
// ...
break;
default:
// ....
}
}


You are warned this is horrible coding practice (however using a map would improve things only slightly though) because type switching can be a maintenance nightmare, using void pointers is not type safe, you have no compiler support and whole heap of other nasty-ness.

C. Using templates and advance template techniques, tricks, and idioms but (not being rude here) i think this option maybe currently beyond you.

D. I'm probably missing a whole lot of other options but i'm tired and its getting very late now, i'm sure some one else will add some others.

[Edited by - snk_kid on June 4, 2005 3:04:29 AM]

Share this post


Link to post
Share on other sites
JohnHurt    334
I think you're misunderstanding what I mean, so I apologise for that.
I don't want a pointer to a member function, I want a member pointer to an external function defined outside the class.

I'm aware of something called Functors, so I'm going to investigate that.

Share this post


Link to post
Share on other sites
fireside    122
I was reading a little about function objects, or functors, a couple days ago. I think they are objects that act as functions, which doesn't quite sound what you want. They sounded kind of useless to me.

Share this post


Link to post
Share on other sites
JohnHurt    334
Thanks for your help guys. I found a compromise, which involves passing everything you could ever need to the event handler function of the widget.

I want a system that's kind of like VB, where the developer provides his own callback for the widgets events, i.e.

void btnOK_Click(......)
{
// close app, or whetever
}

It seems to work quite well now!

Share this post


Link to post
Share on other sites
snk_kid    1312
Quote:
Original post by JohnHurt
I think you're misunderstanding what I mean, so I apologise for that.
I don't want a pointer to a member function, I want a member pointer to an external function defined outside the class.


if you just want a pointer to free-function then its simply:


struct gtGuiWidget {

typedef void (*buttonHandler)();

//.....

protected:

//.....

buttonHandler fpLButtonDownCallback;

void OnLButtonDown() {
fpLButtonDownCallback();
}

//.....

};



Quote:
Original post by JohnHurt
I'm aware of something called Functors, so I'm going to investigate that.


A functor is a function with state, a functional object, you can think of it as function + object = functor. To define one in C++ only involves overloading the function call operator for a user-defined type.

This alone probably doesn't buy you much its mostly useful in generic programming using templates, what i think you mean is generalized functions or an instance of the command design pattern.

If you check out the C++ boost library look into boost::function, it allows to define a signature but store any C++ callable entity; a free-function, member function, even other functors including other instances of boost::function that all conform to the signature. So its a functor aswell. Its currently being reviewed to be included in the C++ standard.

May i suggest an alternative for GUI event-handling though, one of the best ways to do this in C++ is by using a signals & slots library (generalized callback framework). There are many signals & slots libraries out there to use, boost also has a signals & slots library.

Quote:
Original post by fireside
I was reading a little about function objects, or functors, a couple days ago. I think they are objects that act as functions, which doesn't quite sound what you want. They sounded kind of useless to me.


When you start getting deep into using the C++ standard library generic algoritms they will not be as useless as the first appeared to be.

Share this post


Link to post
Share on other sites
deadimp    310
Going back to your first question, I think your problem was getting mixed up with static members. Using the :: scope operator when calling a member of a class tells the compiler that it is static, when, in fact, it isn't, or at least doesn't seem to be in your code.
void gtGuiWidget::OnLButtonDown()
{
//Instead of this: (*gtGuiWidget::fpLButtonDownCallback)();
(*this->fpLButtonDownCallback)(); //Or to get even simpler:
(*fpLButtonDownCallback)();
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this