Question

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;
 test.call_adder(10,20);
 return 0;
}
Was it helpful?

Solution

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.
}

OTHER TIPS

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top