Skip to main content
GameDev.net gamedev.net
🔒 Locked

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

Started by sipickles Sep 7, 2006 at 8:02 AM 4 replies 550+ views
Original Post
sipickles
sipickles
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!
Nitage
Nitage
Is cSimulationLayer::NextStage a static function?
Emmanuel Deloget
Emmanuel Deloget
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,
sipickles
sipickles
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
mikeman
mikeman
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.

Topic Locked

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

Sign in to reply to this topic.