Sign in to follow this  
carb

Complex C++ Function Pointers

Recommended Posts

Hey there, I'm hoping someone can give me a hand. I'm not sure if what I'm proposing is even defined in C++, but here goes. I'm trying to program a simple game, but I'm a big fan of abstraction. I have an Input class with which I'd like to register callback function pointers for certain events from within a GameState class; pointers to that GameState's member functions, specifically. But I can't seem to compile a means of calling such a function pointer from the Input class. I figure if I have an instance to the class, it should be possible. My original thought was something like this...
pState->pfnCallback(params)
Where pState is a pointer to the current GameState class, pfnCallback is a local variable containing the current callback function. Of course all this accomplishes is a mountain of errors, as the compiler wants to look up some function or variable called pfnCallback that exists within the GameState class. So, is there a means of pulling this off? Calling one class's non-static member function from another? Appreciate any help, - Ben

Share this post


Link to post
Share on other sites
Can't use pointers to functions, you need pointer to member function and to use you need an instance of the type or sub-type in question e.g.


#include <iostream>

struct A {

void foo() const {
std::cout << "hello\n";
}

};

struct B {

typedef void (A::*mem_func)() const;

mem_func f;

B(mem_func g): f(g) {}

void do_func(const A& a) {
(a.*f)();
}

};

int main() {

A a;

B b(&A::foo);

b.do_func(a);

return 0;

}


It looks pointless but its a silly example, and it gets more interesting when you have pointer to memeber functions of abstract classes, basically polymorphic indirect calls.

[Edited by - snk_kid on October 17, 2004 1:12:06 PM]

Share this post


Link to post
Share on other sites
I guess I don't see the real difference between what I'm trying to accomplish, except that you use a reference instead of my attempt to use a pointer. Is that necessary, or am I missing the point?

- Ben

Share this post


Link to post
Share on other sites
So basically, I have the following defined ...


typedef const void (CGameState::*PFN_EVENT_CALLBACK)()


And I have a function that takes a pointer to CGameState, and a PFN_EVENT_CALLBACK value. e.g.


CInput::Callback(CGameState *pState, PFN_EVENT_CALLBACK pfnCallback) {
CGameState->pfnCallback()
}


This won't compile.

- Ben

Share this post


Link to post
Share on other sites
What compiler are you using? Gcc is rather strict about ISO compliance with member function pointers, whereas VS (especially 6) lets you get away with a lot (probably not a good thing).

Anywho, from the small section of code you posted, the problem is this:

CGameState->pfnCallback()

Needs to be

(CGameState->*pfnCallback)()


There may also be issues with passing the function pointer parameter itself - namely, gcc requires that it be passed with syntax something like (&Object_Type::Member_Name), whereas VS lets you do all kinds of crazy things when passing the parameter.

Share this post


Link to post
Share on other sites
Why don't you create an input call back class:

class InputCallBack
{
protected:
virtual void DoCallBack (void) = 0; // args/ret can be whatever
};

which is used as:

class AnObject : public InputCallBack
{
private:
virtual void DoCallBack (void)
{
// do something
}
};

and the input class is:

class InputClass
{
public:
void RegisterCallBack (InputCallBack &callback)
{
m_callback = &callback;
}

void DoUpdate (void)
{
if (m_callback)
{
m_callback->DoCallBack ();
}
}

private:
InputCallBack
*m_callback;
};

Which is pretty much the same as function pointers but a bit cleaner. There's probably a name for this pattern but I'm don't know it.

Skizz

Share this post


Link to post
Share on other sites
Quote:
Original post by Skizz
Why don't you create an input call back class:

class InputCallBack
{
protected:
virtual void DoCallBack (void) = 0; // args/ret can be whatever
};

which is used as:

class AnObject : public InputCallBack
{
private:
virtual void DoCallBack (void)
{
// do something
}
};

and the input class is:

class InputClass
{
public:
void RegisterCallBack (InputCallBack &callback)
{
m_callback = &callback;
}

void DoUpdate (void)
{
if (m_callback)
{
m_callback->DoCallBack ();
}
}

private:
InputCallBack
*m_callback;
};



the problem with that code is currently DoCallBack is not visiable to InputClass.

Quote:
Original post by Skizz
Which is pretty much the same as function pointers but a bit cleaner. There's probably a name for this pattern but I'm don't know it.


Off the top of my head the only pattern it resembles is a half written template method which would be:


class InputCallBack {

virtual void do_func() const = 0;

public:

void func() const { do_func(); } //template method

virtual ~InputCallBack() {}

};

class AnObject : public InputCallBack {

void do_func() const { /* ... */ }
};

class InputClass {

const InputCallBack& callback;

public:

InputClass(const InputCallBack& i): callback(i) {}

void do_do() const {
callback.func();
}
};


Unless you was trying to do java style even-handling mechanism, then InputCallBack would be an interface type and its method would be public pure virtual, its what Bjarne's describes as an Action/Action classes. Not very useful in C++ because there aren't any non-static inner & anonymous classes which java has.

The some of the best ways to do event handling & callbacks in c++ are generalized functors or signals & slots, boost has both of these.

[Edited by - snk_kid on October 17, 2004 5:55:22 PM]

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