2

A have a lot of B classes, a class A has one object b. This object b has a function (calc) that needs a pointer to a method in an object of A. This method (fun) acess private variables in class (in my example just return 3).

class A;

class B {
public:
  virtual int calc ( int (A::*fun)())  {    return 2*fun();  };
};

class A {
  B* b;

public:
  A (B* b_) : b (b_) {};
  int fun() { return 3; };
  int run(){ return b->calc(&A::fun); };
};

int main() {
  B* b = new B();
  A a(b);
  a.run();
  return 0;
}

How can I use a pointer to a method correctly in definition of calc method in class B?

I am getting this error message:

teste.cpp:10:58: error: must use ‘.*’ or ‘->*’ to call pointer-to-member     function in ‘fun (...)’, e.g. ‘(... ->* fun) (...)’
   virtual int calc ( int (A::*fun)())  {    return 2*fun();  };
                                                      ^
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • 3
    Pointers to non-static member functions are indeed fun, but you don't work with them like that. I'd look into std::function – UKMonkey Dec 08 '17 at 16:24
  • 3
    Why is a C answer being linked as a duplicate for a C++ question? Calling member functions is not the same as calling functions in C. – wally Dec 08 '17 at 16:40
  • I believe that this is a better duplicate https://stackoverflow.com/questions/12662891/passing-a-member-function-as-an-argument-in-c – UKMonkey Dec 08 '17 at 17:09
  • That is a very strange duplicate for this. – Silvio Mayolo Dec 08 '17 at 23:32

4 Answers4

1

I recommend the std::function approach if it's feasible for you. However, for the sake of completeness, here's how you would correctly use pointer-to-member functions.

The pointer-to-member itself doesn't store the "current" instance of A, so you need to pass that explicitly. Then you use the special ->* (or .*) syntax to call it.

virtual int calc (A* value, int (A::*fun)())  {
  return 2 * (value->*fun)();
};

Then you would call it as b->calc(this, &A::fun);.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
1

You can do it your way, but the member function must be called on a particular instance:

class A;

class B {
public:
    virtual int calc(A* a, int (A::*fun)()) { return 2 * (a->*fun)(); };
};

class A {
    B* b;

public:
    A(B* b_) : b(b_) {};
    int fun() { return 3; };
    int run() { return b->calc(this, &A::fun); }; // now also passing this pointer
};

int main() {
    B* b = new B();
    A a(b);
    a.run();
    return 0;
}

If you can live without calc() being virtual then a lambda is also an option:

class A;

class B {
public:
    template<typename T>
    int calc(T fun) { return 2 * fun(); };
};

class A {
    B* b;

public:
    A(B* b_) : b(b_) {};
    int fun() { return 3; };
    int run() {
        return b->calc([this]() {return fun(); } );
    };
};

int main() {
    B* b = new B();
    A a(b);
    a.run();
    return 0;
}
wally
  • 10,717
  • 5
  • 39
  • 72
0

If you are able to use C++11, then you should use std::function and std::bind: Otherwise you need to use a pointer to member function + a pointer to the instance.

With C++11

#include <functional>

class B {
public:
  virtual int calc (std::function<int()>&& fun) { return 2 * fun();  }; };
};

class A {
  B* b;

public:
  A (B* b_) : b (b_) {};
  int fun() { return 3; };
  int run() { return b->calc(std::bind(&A::fun, this)); };
};

Without C++11

class B {
public:
  virtual int calc (int(A::*fnptr)(), A* a) { return 2 * (a->*fnptr)(); };
};

class A {
  B* b;

public:
  A (B* b_) : b (b_) {};
  int fun() { return 3; };
  int run() { return b->calc(&A::fun, this); };
};

See example here.

user1810087
  • 5,146
  • 1
  • 41
  • 76
0

A pointer-to-class method is defined and initialized as (assuming SomeFn matches the signature):

RetType (ClassName::*pfn)(Args) = &ClassName::SomeFn;

And is called as:

ClassName * ptr = GetClassPtr();
(ptr->*pfn)(arg, arg);
SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23