Sign in to follow this  

Function Pointers

This topic is 3863 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

I'm trying to call a function within an object, and it won't compile (MSVS 2003).
#include <iostream>

using std::cout;

int Foo2()
{
	cout << "Foo2\n";
	return 0;
}

class Ctest
{
public:
	int x;
	Ctest() { x = 9; }
	void TestFunct(int (*functptr)()) {
		cout << "x:  " << x << "\n";
		int p = (*functptr)();
	}
	int Foo2() { cout << "Ctest::Foo2\n"; return 0; }
};

void main()
{
	Ctest t;
	t.TestFunct(Ctest::Foo2);
	// this results in
	// error C2664: 'Ctest::TestFunct' : cannot convert parameter 1 from      
        //'int (__thiscall Ctest::* )(void)' to 'int (__cdecl *)(void)'

}

Sooooo .... what am I doing wrong?

Share this post


Link to post
Share on other sites
The problem is that you're trying to use a non-static member method. Because of this, there is an implicit "this" argument to the method (which is why all member methods have the magical "this" pointer). Because of this, I think that member methods use a different calling convention (__thiscall, from the error message), that is incompatible with a non-member method's calling convention.

One way to fix your compile error is to make Ctest::Foo2 static:


static int Foo2() { cout << "Ctest::Foo2\n"; return 0; }

Share this post


Link to post
Share on other sites
If you are still interested in calling a nonstatic member function from a function pointer, you would have to rewrite the functions.

The main problem is that member functions must be declared as such in the function pointer.
Therefore, Ctest::*functptr needs to be used over just *functptr:
[SOURCE]
void TestFunct(int (Ctest::*functptr)())
{
/*Stuff*/
}
[/SOURCE]


The calling convention is different as well, as the "this" argument needs to be clarified as well.
Instead of just *functptr(), one would need to call this->*fuctptr(), to get a "this" pointer so the function knows what it needs to be called on.

Overall:
[SOURCE]
#include <iostream>

using std::cout;

int Foo2()
{
cout << "Foo2\n";
return 0;
}

class Ctest
{
public:
int x;
Ctest() { x = 9; }
void TestFunct(int (Ctest::*functptr)()) { //Modified function pointer declaration
cout << "x: " << x << "\n";
int p = (this->*functptr)(); //Modified function call
}
int Foo2() { cout << "Ctest::Foo2\n"; return 0; }
};

int main()
{
Ctest t;
t.TestFunct(&Ctest::Foo2);
//This works.
}


Share this post


Link to post
Share on other sites
Cool! Thanks for the insight!

This was just a theoretical experiment. The real question is how is this applicable? I'm thinking this might be useful for dynamically calling functions within an object, but I'm having a hard time wrapping my mind around how this is useful over other methodologies (direct method calls). Any insight?

Share this post


Link to post
Share on other sites
Quote:
Original post by argonaut
Cool! Thanks for the insight!

This was just a theoretical experiment. The real question is how is this applicable? I'm thinking this might be useful for dynamically calling functions within an object, but I'm having a hard time wrapping my mind around how this is useful over other methodologies (direct method calls). Any insight?


Don't worry about it. When you find a use for it, you'll know. Typically it gets used for a really ugly implementation of the Command pattern. Typically at this point, people will tell you that instead of trying to deal with pointers to member functions, you should try out functors, instead.

If you come at it from a purely OO angle instead, you'll likely get a pretty, but non-C++-idiomatic, implementation of the Command pattern. At which point, people will just tell you politely that in C++, we spell that 'Execute()' function in the Command base class' interface as 'operator()()'. :)

Share this post


Link to post
Share on other sites

This topic is 3863 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.

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