views:

248

answers:

2

How can I do this? (The following code does NOT work, but I hope it explains the idea.)

class MyClass  
{  
    ....  
 private:
    int ToBeCalled(int a, char* b);

    typedef (MyClass::*FuncSig)(int a, char* b);

    int Caller(FuncSig *func, char* some_string);
}

I want to call Caller in some way like:

Caller(ToBeCalled, "stuff")

and have Caller call ToBeCalled with whatever parameters it feels needs passing. If at all possible I want to keep everything encapsulated in the private part of my class. In reality, I'd have about 50 functions like ToBeCalled, so I can't see a way to avoid this.

Thanks for any suggestions. :)

+2  A: 

You're most of the way there. You're missing the return type from the typedef, it should be

typedef int (MyClass::*FuncSig)(int, char*);

Now, you just need to use it properly:

int Caller(FuncSig func, int a, char* some_string)
{
    return (this->*func)(a, some_string);
}

You want to pass around plain FuncSig instances, not FuncSig* -- a FuncSig* is a pointer to a pointer to a member function, with an extra unnecessary level of indirection. You then use the arrow-star operator (not its official name) to call it:

(object_to_be_called_on ->* func)(args);

For non-pointer objects (e.g. objects on the stack, or references to objects), you use the dot-star operator:

MyClass x;
(x .* func)(args);

Also, be wary of operator precedence -- the arrow-star and dot-star operators have lower precedence than function calls, so you need to put in the extra parentheses as I have done above.

Adam Rosenfield
Oh my GOD. I can't believe I was that close.I've been messing with this code for 3 hours, and I actually had tried everything you posted at one point.. but apparently I missed one precise combination that was the answer.Thank you very much for your quick answer - it makes me regret not coming here sooner! :)
Stigma
A: 

I'm assuming you tried Caller(MyClass::ToBeCalled, "stuff") already, but is there any particular reason you need a function pointer? Also, please post the actual compiler error.

Stephen Newell
Thanks for your suggestion, and yeah I tried that. :)I am implementing a property handler for Windows 7, but the libraries I am talking to are (too) fond of functions. Add in some legacy versions of files lying around, and you end up needing to check every older fileformat if the newer one is not implemented. The `Caller` function in this case is the testing the various version-formats, and `ToBeCalled` are the actual reader functions which interpret defaultness and such. At least all formats share the same interface. :)
Stigma