Skip to main content
gamedev.net
🔒 Locked

Function pointers - setting in classes

Started by jhavna Jul 22, 2003 at 4:42 AM 7 replies 550+ views
Original Post
jhavna
jhavna
I''ve had a look at http://www.function-pointer.org/ and not found what i am looking for yet (or maybe i just missed it). But say you have a class, call it ClassA, that has a message handler. It also has a function pointer of a defined type (say int function (int, char, float etc), but always the same) In the message handler i want to call the function that the function pointer in ClassA currently points to, after ClassA is done with the message. I know that i need to declare the function pointer with int (TMyClass::*pt2Member)(float, char, char); but the funtion that will be assigned is not always going to be a member of TMyClass. How do i declare the pointer so i can do something like: ClassA objA; AnyClass objAny; objA.set_function (objAny.message_handler); so the above call with set the function pointer in objA to point to the said fucntion in objAny... thanks in advance...
-----------------------"Without a sense of humour we couldn't react to a lot of things"
Trienco
Trienco
sounds like my favorite problem and the only way i found so far includes casting (so it might not be the safest way).


#define METHOD(x) (void(UIBaseObject::*)(void*))&x

class Callback {
private:
UIBaseObject* obj;
void(UIBaseObject::*func)(void*);
public:
Callback() : obj(0), func(0) {}
void Set(UIBaseObject* o, void(UIBaseObject::*f)(void*)) {obj=o; func=f;}

operator()(void* p) {if (obj && func) (obj->*func)(p);}
};


if at any time you have a pointer to the object containing the function you dont need that, but usually when writing a button class you dont know there will be a DialogueToShuffleYourInventory and even less at the point where you call its (for example) OnClick.

so you store a pointer to an instance of the class containing the function and a pointer to the function. you probably read all that much closer than i, so just remember the "obj" in obj->*func will be your "this" within the function. i had some funny effects when accidentally calling it with the button as obj and trying to access elements of the dialogue ,-)

example to use it:

class bla {
public:
Callback OnClick;
};

bla btn;
btn.whenclickedon.Set(Dialogue, METHOD(Dialogue::HandleClick));

btn.whenclickedon(&btn);
(i tend to pass a pointer to the object causing the callback as void*.. for example having one scroll function instead of 4 functions to scroll left,right,up,down and just checking which of the 4 buttons sent the callback).

if you need different return values you can make it a template (improvising):

template
class Callback {
...
R(UIBaseObject::*func)(A);
...
};

for different numbers of arguments i did some ugly overloading (just be damn careful never to use a callback with the wrong number of arguments.. nothing will happen.. literally.. because the function pointer isnt set).
you could of course use that handy ellipse, but then all your callback functions will have some ugly code to extract the arguments.
f@dzhttp://festini.device-zero.de
sbennett
sbennett
AFAIK, you can't do it 'properly' (IE: safely) unless AnyClass inherits TMyClass.

[edited by - sbennett on July 22, 2003 9:48:43 AM]
jhavna
jhavna
yep, that''s what i thought.. nevermind... i''ll just have to think of a way around it.

Thank you both anyhows...
-----------------------"Without a sense of humour we couldn't react to a lot of things"
Trienco
Trienco
quote:
Original post by sbennett
AFAIK, you can''t do it ''properly'' (IE: safely) unless AnyClass inherits TMyClass.


would at least explain why it didnt give me any trouble even though i''m more or less just waiting for it to go wrong. i begin to like that concept of open types *g*

f@dzhttp://festini.device-zero.de
David ONeil
David ONeil
If you make the function a static member function you can develop a framework that works like a charm! Then you will not have to deal with the ''this'' pointer and other stuff. An example is available here. The ''Latest version of ObjWinLib'' zip file has code showing this method (in the WinControlWin class, for example). It also has one section of code showing how to use a class member and ''this'' pointer in the simple ''WinStringGrid'' class.
Trienco
Trienco
the problem with that (if you let it be a problem) is that you cant access any non static members of the class. imagine a button that should minimize the dialogue. either you make the whole dialogue a static class or you have a global instance, else there''s no simple way to change the instance (like setting IsMinimized to true or whatever).
how did you work around that?
f@dzhttp://festini.device-zero.de
Aface
Aface
Am i missing something, or is this the problem that templates are used to overcome? Read the 2nd enginuity article here on gamedev, and look at the functor section.
David ONeil
David ONeil
Trienco:

I implemented a static callback handler which took a (in my case) WinControlWin pointer. Then the static class could simply call back into the actual class object or static_cast it to an object of the correct type and -> use it. You can modify this procedure to your own purposes. You can see the intracies I went through in the WinBaseO unit (WinBaseO::wCommand proc) and the WinCallBackList class at:

http://www.randommonkeyworks.com/Programming/WinAPI_ver2/Project_Begin.html

[edit] - Note that the way I did it my application object has a public WinCallBackList object in it, to be used by the WinBaseO::wCommand proc, amidst other things.

[edited by - david oneil on July 23, 2003 10:39:29 AM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.