views:

54

answers:

1

I know it sounds awefully confusing, I have a base template class which has a function pointer, a child class(which is no longer a template class) needs to use that function pointer to point to a child class's member function, and I get all kinds of errors.. Did I violate some universal law of C++? here is the pseudo code:

template <class T>
class Base{
    public:
       typedef void (Base<T>::*fptr) (char in);
       void funcA(fptr FuncToCall){
                 FuncToCall('a');
       }
       ...
    };

class Child:public Base<char>{
   public: 
       void funcToCall(){...}
       void funcB(){
          funcA(funcToCall);
       }
}

Here is the error message I got:

error C2664: 'Base< T >::funcA' : cannot convert parameter 1 from 'void (__thiscall Child::* )(char)' to 'void (__thiscall Base< T >::* )(char)'

+5  A: 

Your code is invalid.

Firstly, in C++ to create a pointer to a member function you always have to use operator & and a qualified-name of the member, which means that your call to funcA should look as follows

funcA(&Child::funcToCall); // close, but not yet, see "secondly" 

Secondly, member pointers are contravariant. If want to initialize a base-member pointer object with a derived-member pointer value, you have to use an explicit static_cast

funcA(static_cast<fptr>(&Child::funcToCall));

Note that this is a valid, but potentially unsafe conversion, since it is now your responsibility to ensure that the actual object used on the left-hand side of the call (see "thirdly") has that member.

Thirdly, in order to call a function through such a pointer, you have to supply a concrete object on the left-hand side, so the call in funcA should look as follows (I assume that you want to call it for *this object)

(this->*FuncToCall)('a');

Fourthly, your funcToCall is supposed to have a parameter. Where is it?

AndreyT
Thanks, I tried it, i get this error: (similar to the first one)error C2664: 'Base< T >::funcA' : cannot convert parameter 1 from 'void (__thiscall Child::fptr )(char)' to 'void (__thiscall Base< T >::* )(char)'
Yonk
@Yonk: Please, pay attention. Either you forgot to add `static_cast`, as shown in my "secondly", or you are compiling a different code.
AndreyT
Yeah, I added that in, still get a similar error. the only difference is that Child::* became Child::fptr
Yonk
@Yonk: That means that you changed the code from the original version. I'm not telepathic, I don't know what else you've done to it. Your *original* code with my modifications compiles and works fine.
AndreyT
Great, now it appears working, thanks!
Yonk