Search code examples
c++callbackargumentsinherited

Callback argument type does not match in inherited class


I'm trying to implement an event manager based on the linked code in the top answer here: Game Objects Talking To Each Other

However I'm getting an error when I try to register the callbacks. I'm sure it has to do with the typedef, and I admit I'm not sure how it works exactly, but it is in the exact same form in the linked code. The B class should be inherriting from the Interface, so why is the type different? I've condensed the code into the smallest example below.

#include <iostream>

class Interface;
typedef void (Interface::*Callback)(void *data);

class Interface
{
    public:
        void Register    (Callback func);

};

void Interface::Register(Callback func)
{
    std::cout << "Register" << std::endl;
}


class B : public Interface
{
    public:
        B();
        void Echo(void *data);
};

B::B()
{
    Register( (Callback)Echo );
}

void B::Echo(void *data)
{
    std::cout << "Echo" << std::endl;
}


int main()
{
    B b;
    return 0;
}

Here's the error I get under g++ 4.6.1:

test.cpp: In constructor ‘B::B()’:
test.cpp:31:22: error: argument of type ‘void (B::)(void*)’ does not match ‘Callback {aka void (Interface::*)(void*)}’

Could anyone please explain what I'm doing wrong? Thanks


Solution

  • As @Kerrek correctly pointed out, Echo is not a member of Interface, therefore B::Echo doesn't qualify as Interface::*Callback. But you can use a template to accomplish that, e.g.:

    template <class T> class Interface {
    public:
        typedef void (T::*Callback)(void *data);
        void Register(Callback func) {
            std::cout << "Register" << std::endl;
        }
        // ...
    };
    
    class B : public Interface<B> {
    public:
        B() {
            Register(&B::Echo);
        }
        void Echo(void *data) {
            // Do something
        }
    };