Complex C++ Function Pointers

Started by
9 comments, last by Skizz 19 years, 6 months ago
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
- Ben
Advertisement
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]
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
- Ben
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
- Ben
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.
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
(pState->*pfnCallback)();
Yeah, it was completely a syntax issue.

Thanks for all the help.

- Ben
- Ben
Function objects are always cleaner and not susceptible to signature mismatches.
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]

This topic is closed to new replies.

Advertisement