Sign in to follow this  
P3D-BrandonR

C++ class member function pointers ...

Recommended Posts

Hello all, and good morning \ night. I have a question in the way of implementing this feature I am on atm. I have done alot of reading but keep hanging myself up on which way would be the most efficient in achieving this goal. Situation: I have a class object that is a button, cButton for example. This button class, in theory should store a function pointer to it's parent class and link to the parent's class custom function for OnClick() for instance. The parent class, Form1 for example, has a cButton object bound in it and a custom function called OnButton1Click(). In the Constructor of Form1 we set the properties for Button1 object, and set our custom function, OnButton1Click(), as Button1's OnClick() function. I hope I haven't lost anyone yet, it's early in the morning sorry. Anyways, I have seen many ways of doing Method Function Pointers using templates, STL, Boost. I'm just really confused and wondering which would be the most efficient for my needs. Currently I'm not using any additional libraries other than basic c++ and some STL. So I don't see how adding Boost just for this would be bennificial. But any suggestions or examples would greatly be appreciated. Thx so much in advance, Brandon

Share this post


Link to post
Share on other sites
In general a button class shouldn't need to know of the exact type of it's parent. Instead you should try using a generalized callback to be attached to the button's on click handler. For the .NET languages support for this is built-in to the framework with events and delegates, but in pure C++ there are no such handy elements at the language scope. The easiest way to deal with this is to use boost::function as the callback type, and boost::bind to create function objects as object-member function callbacks.

Share this post


Link to post
Share on other sites
This sounds like a good place for a virtual function.


class CButton
{
virtual void OnClick();
}

class CSuperButton() : public CButton
{
virtual void OnClick();
}


Now if you instantiate the CSuperButton class and have some object that takes a pointer to CButton, when that object calls OnClick() the CSuperButton function will be called.

Happy Coding.

Share this post


Link to post
Share on other sites
Quote:
Original post by LordShade
Now if you instantiate the CSuperButton class and have some object that takes a pointer to CButton, when that object calls OnClick() the CSuperButton function will be called.


That sounds what in hindsight I suspect Delphi to be doing. However, something about the idea of deriving a whole new class just to change the behavious of one function sounds plain awful. If you have 100 Buttons in your app that do different things, do you REALLY want to derive 100 classes? Also, it means that the subclass would actually have to be aware of all the data it's function is supposed to affect. So in the end you're more likely to end up with
virtual void() {ptr->functionX();}
to call some function of some known object of some fixed type.

Much more comfortable to have:
Button b = new Button();
b.onClick.bind(ptr, functionX);

The only problem is that the list of parameters and return values must be the same, requiring either extra work or for example a generic pointer as parameter pointing to a more specific struct. That would require a couple of param-structs for different callback types, however.

If it's just supposed to work, use boost. If you want to do it for the heck of it, create your own callback class and try to make it easy and comfortable to use. Then think about using boost ,-)

Share this post


Link to post
Share on other sites
Quote:

So I don't see how adding Boost just for this would be bennificial.


You can include just parts of it. boost::function and boost:bind in this case will make your life exceptionally easier.

Quote:

But any suggestions or examples would greatly be appreciated.



template<typename C=int>
struct mousebinding{
private:
protected:
map<mousecode,function<void(C,C)> > mousemap;

typedef map<mousecode,function<void(C,C)> > maptype;
typedef typename map<mousecode,function<void(C,C)> >::iterator mapiterator;
public:
void mouseinput (mousecode mc, C x, C y);
void bind (mousecode mc, function<void(C,C)> f);
void unbind (mousecode mc);

mousebinding(){}
~mousebinding(){}
};



Where mousecode is a simple enumeration of mouse events and the parameter C is the type of the coordinate system being used. This class is added to a larger class which fans out modifiers [ie shift-click, ctrl-click...] which is added to a larger class along with keyboard bindings, which is added to button sorts of things.

Maybe not the most efficient, but in my experience the easiest by far to use.

Share this post


Link to post
Share on other sites
This forum message is a little screwy if you ask me.

If you're just talking about handling events from buttons, whatever development environment you are writing for has a routine for dispatching messages. Thus, no need to implement anything complicated when a simple switch statement would work. You're gonna be writing a handler regardless on how you bind it. Why not use what's already there?

The example given is a method of remapping dispatch of hardware user-input which I don't think is what he's asking.

Anyway, do it the easy way first. Extreme optimization on UI is not necessary and a waste of your coding efforts. There are many, many clock cycles wasted on doing nothing because a person can only type or mouse click so fast.

I would also like to mention that at some point you ARE going to write non-reuseable code because each application is different. Don't get stuck in the "Object Oriented Conundrum(sp)" where you try to make everything re-usable. Get it to work first, then worry about other things.

Happy coding.

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