Passing a Class member function as a Callback function

Hi
A class I wrote gets a callback function pointer in it's
constructor, and saves it to inform it's creator that
something happned.
Now, when creating an instance of it I need to pass it
a member function of the instance of another class who
creates it.
I keep getting a typecast error message saying It can't
find a matching function in the overloaded functions
with this name.
I only have one function with that name, but it's not
static, so it refuses to accept it.

typedef void (*CallbackFuncType)();

class A
{
   A(int a, int b, CallbackFuncType CallbackFunc};
}

class B
{
   A* m_pA;

   void cb() {...};

   int something()
   {
     m_pA = new A(x, y, (CallbackFuncType)cb);
   }
}        

error C2440: 'type cast' : cannot convert from 'overloaded function type' to 'void (__stdcall *)(void)'
None of the functions with this name in scope match the target type
gilnAsked:
Who is Participating?
 
jasonclarkeConnect With a Mentor Commented:
thanks.
0
 
gilnAuthor Commented:
Edited text of question.
0
 
jasonclarkeCommented:
The typedef is wrong, for member functions you need to pass in the class type to (remember methods take an implicit this pointer),

so you should have:

typedef void (B::*CallbackFuncType)();

to call it, you need to do:

(m_pA->*cb)();




0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
jasonclarkeCommented:
Oh, this won't quite work for you you will need to pass in a pointer to the object into class A together with the constructor, so the A should look like:

typedef void (B::*CallbackFuncType)();

class A
{
public:
   A(int a, int b, B* theb, CallbackFuncType cb};
   void CallIt() { (theb->*cb)(); }
}

This doesn't help if you want to pass callback functions from any class into A.  I can show you away around this that makes the cb function type into a templated class to solve the problem.



0
 
gilnAuthor Commented:
The whole idea is I need to avoid from class
A knowing class B,
If this is the only solution, it doesn't help me
since in such case I will hold a pointer to B,
and implicitly call the function.
0
 
gilnAuthor Commented:
The whole idea is I need to avoid from class
A knowing class B,
If this is the only solution, it doesn't help me
since in such case I will hold a pointer to B,
and implicitly call the function.
0
 
jasonclarkeCommented:
You can use something like the following then:

class AbstractCallback {
public:
    virtual void operator()() = 0;
};

template <class T>
class SimpleCallback : public AbstractCallback  
{
public:
    typedef void (T::*CB)();

    SimpleCallback(T* instance, CB callback)
        : mInstance(instance), mCallback(callback)
{}

    virtual ~SimpleCallback() {}

    virtual void operator()() {
        (mInstance->*mCallback)();
    }
protected:
    T* mInstance;
    CB mCallback;
};

class A
{
public:
    A(int a, int b, AbstractCallback* cb)
        : mCb(cb),  //...

    virtual ~A() { delete mCb; }

    void CallFunction() {
        (*mCb)();
    }
private:
    AbstractCallback* mCb;
};

class B
{
public:
     void CallbackFunc() { }
     int something()
     {
         m_pA = new A(x, y, new SimpleCallback<A>(this, CallbackFunc); );
     }
};




0
 
gilnAuthor Commented:
Answer so I can credit you
0
 
gilnAuthor Commented:
Small correction : ***

class B
{
public:
     void CallbackFunc() { }
     int something()
     {
         m_pA = new A(x, y, new SimpleCallback<B>(this, CallbackFunc); );
     }
};

0
 
jasonclarkeCommented:
Yes, sorry about that.

You note that the receiver of the callback takes responsibility for deleting the it.  This does not have to be the case, but you should be aware that if it does, you must create a new instance of the SimpleCallback every time you set a callback.

And since the object must be created on the heap, you probably should change SimpleCallback to look like:

template <class T>
class SimpleCallback : public AbstractCallback    
{
public:
    typedef void (T::*CB)();

    SimpleCallback* Create(T* instance, CB callback)
    { return new SimpleCallback<T>(instance, callback) };

    virtual ~SimpleCallback() {}

    virtual void operator()() {
        (mInstance->*mCallback)();
    }
protected:
    SimpleCallback(T* instance, CB callback)
        : mInstance(instance), mCallback(callback)
    {}

    T* mInstance;
    CB mCallback;
};




0
 
jasonclarkeCommented:
the Create function should have been static!
0
All Courses

From novice to tech pro — start learning today.