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

Function Pointers inside a class

Started by Happypuppet Aug 5, 2006 at 2:03 PM 4 replies 750+ views
Original Post
Happypuppet
Happypuppet
It seems that almost every time I look at a function pointer tutorial dealing with member functions, it ALWAYS explains how to get a pointer on the outside to reference to a function inside a class. This leads me to assume that standard function pointer syntax applies when you're getting a function pointer inside Class A to point to a function inside Class A. Except that doesn't want to work either. What I'm trying to do here is create a function that will clear out a linked list. Optionally, it will call a function for each node in the list just before it's cleared out. Snippet with changed identifiers:

cClass
{

struct sNode; // Contents not important

void EmptyList(void (* nodefunc)(sNode*))
	{
		sNode* tmp;
		// Code to carry tmp through the linked list
		if( nodefunc != NULL ) nodefunc(tmp); // Executed for each node
	}

void Func(sNode* node)
	{
		// code using the node
	}

~cClass()
	{
		EmptyList(NULL);
	}

void ClearWithFunc()
	{
		EmptyList(Func); // *** ERROR ***
	}

};

The error I get from the marked line is (using Visual Studio .NET 2003) error C2664: 'cClass::EmptyList' : cannot convert parameter 1 from 'void (cClass::sNode *)' to 'void (__cdecl *)(cClass::sNode *)' No errors occur when the offending line is commented out. The line in the destructor works just fine. I have tried a very large number of things, one such thing being moving the function pointer from being a function parameter to a member variable. Nothing's worked so far. Anyone know what to do?
Enigma
Enigma
Func is a member function, but EmptyList takes a pointer to non-member function. A pointer to member function cannot (portably) be converted to a pointer to non-member function, since a pointer to member function usually contains additional information about the class.

You could just change EmptyList to take a pointer to member function (void EmptyList(void (cClass::* nodefunc)(sNode*))), but that wouldn't be very flexible. You could also change Func to a non-member or static member function, but that's still not as flexible. A better alternative is to use functors. The Boost libraries include Boost.Function and Boost.Bind, which have also been adopted into the C++ Standard TR1. These allow you to create functors from member and non-member functions and pass them around:

class Class{	struct Node; // Contents not important	void EmptyList(boost::function< void (sNode *) > const * nodefunc = 0)	{		Node* tmp;		// Code to carry tmp through the linked list		if (nodefunc != NULL)		{			(*nodefunc)(tmp); // Executed for each node		}	}	void Func(Node* node)	{		// code using the node	}	~Class()	{		EmptyList();	}	void ClearWithFunc()	{		EmptyList(boost::bind(&Class::Func, this, _1));	}};

Σnigma
Happypuppet
Happypuppet
Quote:
Original post by Enigma
Func is a member function, but EmptyList takes a pointer to non-member function. A pointer to member function cannot (portably) be converted to a pointer to non-member function, since a pointer to member function usually contains additional information about the class.

You could just change EmptyList to take a pointer to member function (void EmptyList(void (cClass::* nodefunc)(sNode*))), but that wouldn't be very flexible.


1. Is the loss of flexibility referring to the fact that the list could only be emptied with calling a member function? As opposed to any accessible function whether global, local member, or member of another class. Not positively certain what you were referring to.

2. I actually had already tried changing the function parameter to what you said above. This was the resulting error.

On the line reading: if( nodefunc != NULL ) nodefunc(tmp);
error C2064: term does not evaluate to a function

Just in case the (*nodefunc)(tmp) was a correction not related to the usage of Boost, I tried changing nodefunc(tmp) to (*nodefunc)(tmp) (as seen in your second example). That does not solve the error and gives another one about the * being misplaced.

Quote:
Original post by Enigma
A better alternative is to use functors. The Boost libraries include Boost.Function and Boost.Bind, which have also been adopted into the C++ Standard TR1. These allow you to create functors from member and non-member functions and pass them around.


Never heard of this Boost... am currently browsing the site for information as I write this reply. How portable is it? The "project" that I'm working on involving this snippet of code I had in the first post is a framework that I am trying to make as portable as possible, usable with any platform or decent compiler. (I might be able to answer this by browsing the site...)

Thanks for the reply.
KrazeIke
KrazeIke
Quote:

2. I actually had already tried changing the function parameter to what you said above. This was the resulting error.

On the line reading: if( nodefunc != NULL ) nodefunc(tmp);
error C2064: term does not evaluate to a function


Here's the non-boost solution:

class cClass{struct sNode; // Contents not importantvoid EmptyList(void (cClass::* nodefunc)(sNode*))	{		sNode* tmp;		// Code to carry tmp through the linked list		if( nodefunc != NULL ) 			(this->*nodefunc)(tmp); // Executed for each node	}void Func(sNode* node)	{		// code using the node	}~cClass()	{		EmptyList(NULL);	}void ClearWithFunc()	{		EmptyList(&cClass::Func);	}};
Enigma
Enigma
Quote:
Original post by Happypuppet
1. Is the loss of flexibility referring to the fact that the list could only be emptied with calling a member function? As opposed to any accessible function whether global, local member, or member of another class. Not positively certain what you were referring to.

Yes. With a pointer to non-member function you can only use non-member and static member functions. With a pointer to member function you can only use member functions of the specified class. With Boost.Function you can use just about anything.
Quote:
2. I actually had already tried changing the function parameter to what you said above. This was the resulting error.

On the line reading: if( nodefunc != NULL ) nodefunc(tmp);
error C2064: term does not evaluate to a function

I meant to post a link to what used to be function-pointer.org, which explains a bit more about pointers to member functions. Basically a pointer to a member function needs an object on which it can act as a member function. The calling syntax is (object.*member_function_pointer)(parameters);.
Quote:
Just in case the (*nodefunc)(tmp) was a correction not related to the usage of Boost, I tried changing nodefunc(tmp) to (*nodefunc)(tmp) (as seen in your second example). That does not solve the error and gives another one about the * being misplaced.

Yes, that change was specific to using Boost.Function.
Quote:
Never heard of this Boost... am currently browsing the site for information as I write this reply. How portable is it? The "project" that I'm working on involving this snippet of code I had in the first post is a framework that I am trying to make as portable as possible, usable with any platform or decent compiler. (I might be able to answer this by browsing the site...)

Boost is nearly as portable as the C++ Standard Library. It's a collection of libraries, so portability does vary from library to library, but for most of Boost if you can find a compiler that it doesn't work on it's probably not a very good compiler. Many of the Boost libraries have been or are being proposed for the next C++ Standard, at which point they (or variations thereof) will become part of the C++ Standard Library and thus theoretically as portable as C++.

Σnigma
dbzprogrammer
dbzprogrammer
This is a little off topic, but just for future reference:

You're original code would work if the "Func" function was a friend or static function, and when you call EmptyList(), you put in (&cClass::Func).
We should do this the Microsoft way: "WAHOOOO!!! IT COMPILES! SHIP IT!"

Topic Locked

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

Sign in to reply to this topic.