Sign in to follow this  
bluepig.man

A problem about a pointer to member function?

Recommended Posts

bluepig.man    424
L have declare two function like this:

[source lang="cpp"]void order( void (*visit) (int,int) );
void visit(int,int);[/source]

They are member function in the same class?
And l want call order like this:

[source lang="cpp"]oder(visit);[/source]

but it can't pass.
How can l do this?

Share this post


Link to post
Share on other sites
Hodgman    51326
You're using a regular pointer-to-function, not a pointer-to-member-function.
The syntax for pointer-to-member-functions looks like:
[code]
class Foo
{
public:
void order( void (Foo::*visit) (int,int) )
{
(this->*visit)(1,2);
}
void visit(int x, int y)
{
printf("%d, %d\n", x, y);
}
void test()
{
order(&Foo::visit);
}
};[/code]

Share this post


Link to post
Share on other sites
Hodgman    51326
That's the syntax for calling a [i]pointer-to-member-function[/i].

It's a bit confusing because you've called both a variable and a function "visit", so I'll pretend the [font=courier new,courier,monospace]order[/font] definition is instead:
[font=courier new,courier,monospace]void order( void (Foo::*[b]fn[/b]) (int,int) )[/font]

"[font=courier new,courier,monospace]fn[/font]" is a pointer, so "[font=courier new,courier,monospace]*fn[/font]" dereferences that pointer as usual. [font=courier new,courier,monospace]fn[/font] was a [i]pointer-to-member-function[/i], so [font=courier new,courier,monospace]*fn[/font] is just a [i]member-function[/i].
i.e. [font=courier new,courier,monospace]fn[/font] is "[font=courier new,courier,monospace]&Foo::visit[/font]" and [font=courier new,courier,monospace]*fn[/font] is "[font=courier new,courier,monospace]Foo::visit[/font]"

"[font=courier new,courier,monospace]object->[/font]" is the regular syntax for accessing members of an object.
Normally you don't have to write "[font=courier new,courier,monospace]this->[/font]" in front of members, but you can if you want to -- e.g. in [font=courier new,courier,monospace]test[/font] you could write "[font=courier new,courier,monospace]this->order(blah);[/font]" and it would mean the same as "[font=courier new,courier,monospace]order(blah);[/font]".

So going off the above, [font=courier new,courier,monospace](this-> *fn)[/font] ends up meaning [font=courier new,courier,monospace]this->visit[/font], which is the same as just saying [font=courier new,courier,monospace]visit[/font].
We need to wrap it in parenthesis ([font=courier new,courier,monospace]()[/font]) and have to include the "[font=courier new,courier,monospace]this->[/font]" because of the weird way that [i]pointer-to-member-function[/i] syntax works ;)

So then, [font=courier new,courier,monospace](this-> *fn)(1, 2)[/font] is the same as [font=courier new,courier,monospace]visit(1,2)[/font], which ends up printing "[font=courier new,courier,monospace]1 2[/font]".

[edit]As wqking corrected below "[font=courier new,courier,monospace]-> *[/font]" shouldn't have a space in it and should be "[font=courier new,courier,monospace]->*[/font]" Edited by Hodgman

Share this post


Link to post
Share on other sites
wqking    761
[quote name='Hodgman' timestamp='1354004413' post='5004444']
So going off the above, [font=courier new,courier,monospace](this-> *fn)[/font] ends up meaning [font=courier new,courier,monospace]this->visit[/font], which is the same as just saying [font=courier new,courier,monospace]visit[/font].
[/quote]

I think -> * should be ->* because it's a single operator and we can even overload it.

OP, try to Google for "c++ pointer to member operator", no quote mark.
Here are some search results,
http://msdn.microsoft.com/en-us/library/k8336763%28v=vs.80%29.aspx
http://stackoverflow.com/questions/6586205/what-are-the-pointer-to-member-and-operators-in-c

And Hodgman's reply. :-)

Share this post


Link to post
Share on other sites
KaiserJohan    2317
I highly, highly recommend looking into Boost function ([url="http://www.boost.org/doc/libs/1_52_0/doc/html/function.html"]http://www.boost.org/doc/libs/1_52_0/doc/html/function.html[/url]). I use it for some callbacks and it works wonders.

Share this post


Link to post
Share on other sites
BitMaster    8651
[quote name='KaiserJohan' timestamp='1354012194' post='5004470']
I highly, highly recommend looking into Boost function ([url="http://www.boost.org/doc/libs/1_52_0/doc/html/function.html"]http://www.boost.org/doc/libs/1_52_0/doc/html/function.html[/url]). I use it for some callbacks and it works wonders.
[/quote]

Or std::function and/or lambdas on C++11 capable compilers.

Share this post


Link to post
Share on other sites
Shannon Barber    1681
You are probably much better off learning about 'Interfaces' to solve this problem if you are going to use a pointer-to-a-member-function to solve it.

[code]
class ITweakable
{
public:
void TweakMe(void) = 0;
}

class Tweakie : ITweakable, IThwackable, //etc...
{
public:
void TweakMe(void)
{
g_Audio->StartPlayback('giggle.ogg');
}
void ThwackMe(void)
{
g_Audio->StartPlayback('oouff.ogg');
}
}

class TweakHerder
{
public:
AddTweakie(ITweakable* tweakie)
{
this->myTweakies.push_back(tweakie);
}
void TimeToTickleTheTweakies(void)
{
//Not C++ because C++ syntax for this is dog-pile
foreach(ITweakable* tweakie in myTweakies)
{
tweakie->TweakMe();
}
}
private:
list<ITweakable> myTweakies;
}
[/code]

And there ya' go, entertainment for a toddler for hours.

Share this post


Link to post
Share on other sites
BitMaster    8651
Going whole interfaces for a single functor is a bit of overkill and often the sign of Javaisms creeping into C++ (not trying to whack on Java here, but the two languages require a very different mindset).

There is a reason C++ finally got a proper std::function and lambdas and that is because there are many cases where a full-blown interface just is not the right choice.

Edit: there is also the issue of a true interface always introducing runtime polymorphism (again something that is not an issue with a JITed Java but a potential issue in C++ where runtime polymorphism is often not needed and compile time polymorphism would be enough). But that is just going off on a tangent here... Edited by BitMaster

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