Передача указателя метода для нового метода в базовый класс

Я хотел бы иметь возможность вызывать любой произвольный метод (который является универсальным методом), определенный в производном классе от базового класса. Базовый класс не знает о них. Я хотел бы получить этот указатель и смещение виртуальной таблицы и иметь возможность вызывать его. Класс A на самом деле не должен быть базовым, это может быть отдельный класс, который ничего не знает о B, но должен вызывать методы. Является ли это возможным?

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);

2 ответа

Решение

Вы можете использовать шаблон CRTP, чтобы выполнить то, что вы пытаетесь.

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);
   }
};

Нестатическим функциям-членам необходим объект, на который можно воздействовать, поэтому вы не можете просто вызвать указатель на функцию-член сам по себе. Вы можете определить шаблон для вызова члена любого класса, учитывая объект этого класса:

template <class Class>
void call(Class & c, void (C::*method)()) {
    (c.*method)();
}

Если это не то, что вы хотите, то вам нужно уточнить, что вы хотите.

Другие вопросы по тегам