Search code examples
c++vtable

Passing a method pointer for a new method to base class


I'd like to be able to call any arbitary method (which are generic methods) defined in a derived class from the base class. The base class doesn't know about them. I'd somehow like to get this pointer and the virtual table offset and be able to call it. Class A doesn't actually need to be the base class, it could be a separete class which doesn't know anything about B but needs to call the methods. Is it possible?

class A
{
public:
    typedef void (A::*Method)();

    void call(Method p)
    {
        //...
    }
};


class B : public A
{
public:
    virtual void meth1()
    {
    }
    virtual void meth2()
    {
    }
    virtual void test()
    {
        call(&TestTask::meth1);
        call(&TestTask::meth2);
    }
};

Errors:
test.cpp:420:30: error: no matching function for call to ‘B::call(void (TestTask::*)())’
         call(&TestTask::meth1);
                              ^
test.cpp:420:30: note: candidate is:
test.cpp:402:10: note: void A::call(A::Method)
     void call(Method p)
          ^
test.cpp:402:10: note:   no known conversion for argument 1 from ‘void (TestTask::*)()’ to ‘A::Method {aka void (A::*)()}’
test.cpp:421:30: error: no matching function for call to ‘B::call(void (TestTask::*)())’
         call(&TestTask::meth2);

Solution

  • You can use the CRTP pattern to accomplish what you are trying.

    template <typename T> struct A
    {
       typedef void (T::*Method)();
    
       void call(Method m)
       {
          (static_cast<T*>(this)->*m)();
       }
    };
    
    struct B : A<B>
    {
       void meth1(){}
       void meth2(){}
    
       void test()
       {
          call(&B::meth1);
          call(&B::meth2);
       }
    };