Archived

This topic is now archived and is closed to further replies.

Function Pointers

This topic is 5015 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi I was just wondering if you can have a pointer to a method in a class. I have created a gui with callback functions and wanted the callbacks I created to be part of my main game class. It only works though if I make them static.( not desired ). Is there way around this. a sample of my code is: //in my gui CoreComponent header //this is my callback pointer typedef void(*ComponentCallback)( CoreComponent * caller ); class CoreComponent { ... void SetEventCallback( EventType event, ComponentCallback callback ); ... }; //in global space void testCallback( CoreComponent * caller ) { ...//some stuff here } //in game core class GameCore { ... void callback( CoreComponent * caller ); ... } void GameCore::Run() { CoreComponent c; c.SetEventCallback( testCallback ); //this works fine CoreComponent c2; c2.SetEventCallback( this->callback ); //doesn''t work unless //GameCore::callback //is static } Can I force this->callback above to be a vaild function pointer? The error I get is something like: cannot convert from void callback * to void (__cdecl) callback * casting to (__cdecl) doesn''t work. Any help is appreciated. Thanks. Pete

Share this post


Link to post
Share on other sites
there are a few ways around this.
1) you could pass a pointer to the object you want to call the method on to the static method ala


class GameCore
{

//.... inlined for simplicity


static void callBack(void* pObj)
{
if (GameCore* pCore = (GameCore*)pObj) {
pObj->callBack();
}
}

void callBack()
{
//whatever

}
};

that's how a lot of MS api's work but it's a bit nasty and type-unsafe

the other way is to define a callback interface and require callback classes to inherit from it, then just pass the object


struct ICallBack
{
virtual void callBack() = 0;
};

class GameCore : public ICallBack
{
void callBack()
{
//whatever

}
}

// then call the method on the object

void SetEventCallback( EventType event, ICallBack& callBack)
{
// do event handling


callBack.callBack();

}




AFAIK you can't pass a pointer to a non-static member function, although I could be way off on this.


[edited by - ChaosEngine on March 24, 2004 6:56:20 PM]

Share this post


Link to post
Share on other sites
You can definitely have pointers to non-static member functions, but they have some restrictions to them, specifically that the class the member function belongs to is considered part of the function signature for all practical purposes. And the actual syntax for calling the member function is ... odd.

For instance:

#include <iostream>
using namespace std;

class Foo {
public:
void bar() { cout << "Foo::bar" << endl; }
};

typedef void(Foo::*MemFn)();

int main() {
Foo foo;
MemFn fn = &Foo::bar;
(foo.*fn)();
Foo* pFoo = new Foo();
(*pFoo.*fn)();

return 0;
}


Hope that helps,
- Neophyte

EDIT: Forgot to close the source tag.

[edited by - Neophyte on March 24, 2004 7:32:50 PM]

Share this post


Link to post
Share on other sites
I tried this:


////////////////////////////////////////////
#include <stdio.h>
#include <conio.h>

class ICB
{
public:
typedef void (ICB::*ICB_CALLBACK)();

void ICB_Func()
{
printf("\nIn ICB callback\n");
}

};

class A
{
public:
void SetCallBack( ICB::ICB_CALLBACK c ){ curCB = c; }
void RunCallBack(){ curCB(); }

protected:
ICB::ICB_CALLBACK curCB;
};


void main()
{

A aTest;
aTest.SetCallBack( ICB::ICB_Func );
aTest.RunCallBack();

getch();
};
///////////////////////////////////////


but in this line in class A :

void RunCallBack(){ curCB(); }

I get the error curCB() term does not evaluate to a function

Share this post


Link to post
Share on other sites
I figured something out thats works well for me. It uses templates and means I can only set callbacks on a specific component from the one class. This is''nt to bad though and keeps the code very clean. Have a look:

////////////////////////////////////////////////////////////

#include <stdio.h>
#include <conio.h>


//the component is templated so that it can
//recieve callbacks from one specified class
template < class T >
class CoreComponent
{
public:

void SetCallBack( T::CALLBACK cb )
{
callback = cb;
}

void RunCallBack()
{
T cb;
(cb.*callback)();
}

T::CALLBACK callback;
};


//define a macro to define a callback pointer specific
//to the passed in class type T
#define DefineComponentCBPointer(T) typedef void(T::*CALLBACK)()


//GameCore will contain all callbacks in this program
class GameCore
{
public:

//make sure this is called BEFORE any CoreComponents are created
DefineComponentCBPointer(GameCore);

void Run()
{
CoreComponent< GameCore > test;
test.SetCallBack( testCallBack );
test.RunCallBack();
}

void testCallBack()
{
printf("\nIn Game Core::TestCallBack\n");
}
};


//test it
void main()
{
GameCore gc;
gc.Run();
getch();
};

///////////////////////////////////////////////////////////


This works great! Thanks for all the help everyone. It''s appreciated.

Pete

Share this post


Link to post
Share on other sites