3

I have 2 classes

class B {
public:
    int func(int i);
};

class A {
public:
    typedef int (B::*fPtr)(int);
    void run();
    B* mB;
};

void A::run() {
    // create a pointer
    fPtr p = &(B::func);
    // invoke the function
    mB->*p(2);     <------- Compilation Error
}

What i need is to create a pointer to func() in A's run function. I get a compilation error saying that mB is not corresponding to a function with 1 argument.

please help

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Alex Kul
  • 33
  • 1
  • 1
  • 4
  • Why are you making this so complicated? Why have you tagged it with inheritance - when you are not using it? Have you heard of interfaces? – Ed Heal Dec 22 '11 at 06:09
  • 1
    Why not use a std::function/boost::function? They tend to be much more flexible and much simpler to use than stupid C style function pointers. –  Dec 22 '11 at 06:26
  • 1
    @EthanSteinberg Member function pointers have little/nothing to do with C function pointers, and cannot be stored in `std/boost::function` – Benjamin Lindley Dec 22 '11 at 06:30
  • @BenjaminLindley It's trivial to store member function in a std::function. Example in this case would be `std::function fun = &B::func`. Then the call would be a much less convoluted `fun(mB,2);` –  Dec 22 '11 at 06:36

3 Answers3

6

You need to put parentheses around the function expression:

(mB->*p)(2);

But as others have pointed out, there's almost certainly a better way to do what you're trying to do.

Sean
  • 29,130
  • 4
  • 80
  • 105
  • First of all, thanks for the help. as for using other things mentioned above, I think that this solution is the most suitable one in my case – Alex Kul Dec 22 '11 at 06:54
2

Instance methods on a class always have a hidden first parameter for the this pointer, thus it is incompatible with your function pointer typedef. There is no way directly to obtain a pointer to a member function. The typical workaround is to use a "thunk" where you pass a static function that accepts a generic "catch all" parameter (such as void *) which can be statically cast to a pointer of your choosing on which you can invoke the member function. Example:

class B
{
public:
    static void MyThunk(void * obj)
    {
        static_cast<B *>(obj)->MyRealFunc();
    }

    void MyRealFunc()
    {
        // do something here
    }

    // . . .
};

You can get a pointer to the static function easily as it has no 'hidden this', just reference it using B::MyThunk. If your function requires additional parameters, you can use something like a functor to capture the necesssary parameters and state.

You should definitely read this C++ FAQ Lite page which tells you much more about all this: Pointers to member functions

bobbymcr
  • 23,769
  • 3
  • 56
  • 67
  • Good answer. Why does the type of `obj` have to `void *`? I would prefer `B *`. – David Grayson Dec 22 '11 at 06:36
  • @bobbymcr: I take it that you have never worked with the `->*` and `.*` operators before? They do allow calling methods on object instances via pointers, just as Alex's example showed. He was ust missing a set of parenthesis to make his code compile correctly. – Remy Lebeau Dec 22 '11 at 06:37
  • 1
    @DavidGrayson: Usually you have to use some "bare bones" pointer type to interop with things like `CreateThread` on Win32 which only lets you pass `LPVOID` to your `ThreadStart` function pointer. You should of course make things as strongly typed as you can, but you don't always have a choice. – bobbymcr Dec 22 '11 at 06:49
1

why can you not call mB->func(2);?

If you need different functions for B perhaps look into virtual functions and class inheritance

smitec
  • 3,049
  • 1
  • 16
  • 12