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
  • 505,946
  • 29
  • 409
  • 696
Alex Kul
  • 33
  • 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
  • 28,226
  • 4
  • 76
  • 103
  • 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,123
  • 3
  • 53
  • 66
  • 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
  • Yesterday I accidentally downvoted you. I meant to click the other arrow, but evidently I failed my internet sobriety test. Please don't be distraught by this devastating blow to your reputation. It's not you... it's me... (P.S. maybe I'll find this answer edited one day and fix it? I can't find anything to edit myself) – Gary Mar 11 '15 at 03:39
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,029
  • 1
  • 14
  • 12