Sign in to follow this  
sipickles

[C++] Another function pointer query - passing as arguments

Recommended Posts

Hello, I am trying to grasp function pointers, particularly to use as callbacks in my GUI. Can anyone explain what I have done wrong here, when trying to pass a function pointer?
class cTimer 
{
public:
	cTimer();
	
	void SetCallback( void (*ptrTimeOut)( void ) );

	void Start( float target );

	bool Update( void );

	void (*ptrTimeOut)( void );
//	void (cTimer::*ptrTimeOut)( void );
//	inline void TimeOut( void ) { (*this.*ptrTimeOut)(); }

protected:
	float m_time;
	float m_target;
};



// Then in my main class, cSimulationLayer

void cSimulationLayer::NextStage()
{
       m_stage++;
}

void cSimulationLayer::Init()
{
	m_timer				= new cTimer();
	m_timer->SetCallback ( cSimulationLayer::*NextStage() );
// or.....
	m_timer->SetCallback ( &(cSimulationLayer::NextStage()) );

}


I think I am close!

Share this post


Link to post
Share on other sites
To enhance Nitage's answer: you can't treat non-static member function as normal functions. They need extra data to work (namely, a "this" pointer). However, static member function don't have this requirement, and thus can be used as normal, non member functions when it comes to catsing them to a function pointer.

Regards,

Share this post


Link to post
Share on other sites
Its not a static function.

I thought that it would be okay since its local to the function call thats supplying the function pointer... but I guess its not local to the cTimer class during the actual call.

In that case how do I supply a function pointer to the cTimer class?

I'm obviously wanting each instantiation of the timer to call a different function when it has expired:

m_timer->SetCallback( &(g_simulationLayer->NextStage()) );
m_timeOut->SetCallback( &(g_simulationLayer->RestartGame()) );
m_messageEventTimer->SetCallback( &(m_eventManager->RandomEvent()) );

When I do this sort of thing, the error is all about & needed a lhs value. I hoped the & would be providing the pointer!

Thanks

Si

Share this post


Link to post
Share on other sites
In that case, you need to somehow store both the member function address and the instance(the "this" pointer).

I strongly recommend to take a look at boost, especially boost::function and boost::bind(SC++L has similar functionality with mem_fun and bind1st/bind2nd but not as powerful). Using those, the code would simply become:


class cTimer
{
public:
cTimer();

void SetCallback( boost::function< void(void) > );
...
};

m_timer->SetCallback( boost::bind(&cSimulationLayer::NextStage,&g_simulationLayer) );







Every non-static member function actually has one more parameter than it appears: the first parameter is always the "this" pointer, which is implicitly passed. For example, when you call g_simulationLayer.NextStage(), you actually call cSimulationLayer::NextStage(&g_simulationLayer).

What you do here is just "bind" the first parameter of cSimulationLayer::NextStage(the "this" pointer) to &g_simulationLayer.

You can even take this a step further and "bind" other parameters of the callback for later use. For example, let's say you have member function ChangeColor:


class SomeClass
{
void ChangeColor(float r,float g,float b)
{
...
}
};







If you want timer1 to change the color of instance1 to (1,0,0) and timer2 to change the color of instance2 to (0,0,1):

timer1->SetCallback( boost::bind(&SomeClass::ChangeColor,&instance1,1,0,0) );
timer2->SetCallback( boost::bind(&SomeClass::ChangeColor,&instance2,0,0,1) );

From my experience this is extemely useful.

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