There are several duplicates of this but nobody explains why I can use a member variable to store the pointer (in FOO
) but when I try it with a local variable (in the commented portion of BAR
), it's illegal. Could anybody explain this?
#include <iostream>
using namespace std;
class FOO
{
public:
int (FOO::*fptr)(int a, int b);
int add_stuff(int a, int b)
{
return a+b;
}
void call_adder(int a, int b)
{
fptr = &FOO::add_stuff;
cout<<(this->*fptr)(a,b)<<endl;
}
};
class BAR
{
public:
int add_stuff(int a, int b)
{
return a+b;
}
void call_adder(int a, int b)
{
//int (BAR::*fptr)(int a, int b);
//fptr = &BAR::add_stuff;
//cout<<(*fptr)(a,b)<<endl;
}
};
int main()
{
FOO test;
开发者_StackOverflow社区 test.call_adder(10,20);
return 0;
}
Apparently, you misunderstand the meaning of this->*
in the call in FOO
.
When you use this->*
with the member fptr
pointer, the this->*
part has absolutely nothing to do with fptr
being a member of FOO
. When you call a member function using a pointer-to-member, you have to use the ->*
operator (or .*
operator) and you always have to specify the actual object you want to use with that pointer-to-member. This is what the this->*
portion of the calling expression does. I.e. the call will always look as
(<pointer-to-object> ->* <pointer-to-member>) (<arguments>)
or as
(<object> .* <pointer-to-member>) (<arguments>)
The left-hand side of the call (<pointer-to-object>
or <object>
above) cannot be omitted.
In other words, it doesn't matter whether fptr
is a member variable, local variable, global variable or any other kind of variable, the call through fptr
will always look as
(this->*fptr)(a, b);
assuming that you want to invoke it with *this
object. If, for another example, you want to invoke it for some other object pointed by pointer pfoo
, the call will look as follows
FOO *pfoo;
...
(pfoo->*fptr)(a, b);
In your BAR
class the call should look as (this->*fptr)(a,b)
even though fptr
is a local variable.
When you use a member function pointer, you need to specify the object on which it is acting.
I.e. you need to create a pointer to an instance of BAR (let's call it bar
) and do:
(bar->*fptr)(a,b)
to call the function, or an instance of BAR and do:
(bar.*fptr)(a,b)
Put another way:
#include <iostream>
class BAR
{
int i;
public:
BAR(): i(0) {};
int AddOne() { return ++i; };
int GetI() { return i; };
}
int main()
{
BAR bar;
auto fPtr = &BAR::AddOne; // This line is C++0x only (because of auto)
std::cout << (bar.*fPtr)(); //This will print 1 to the console
std::cout << std::endl;
std::cout << bar.GetI(); //This will also print 1 to the console.
}
I don't think the usage of the variable itself is illegal. What's illegal is trying to call that method without a class instance.
That is, you should really call (someVar->*fptr)(a,b)
where someVar
is of type BAR*
BAR::call_adder()
had a couple of problems. For one, you were mixing case. In C++, case is signifigant. BAR
and bar
are not the same. Second, you decalred and assigned the pointer fine, after fixing the case problems, but when you try to call through the pointer to a member function, you need to use operator ->*
with a class object. Here's is call_adder()
fixed
void call_adder(int a, int b)
{
int (BAR::*fptr)(int a, int b);
fptr = &BAR::add_stuff;
cout<<(this->*fptr)(a,b)<<endl;
}
When you invoke a member function of a class the compiler generates code to set 'this' while the function runs. When you call it from a function pointer that isn't done. There are ways to get around it but they aren't 'guaranteed' to work and are compiler dependent. You can do it as long as you're careful and know the possible problems you can run into.
精彩评论