指向类方法的多个指针

Multiple pointers to class methods

本文关键字:指针 类方法      更新时间:2023-10-16

我有一个类,它应该保存一个指向各种类的方法的指针,并通过它调用它们。

有点像这里,但有一个小的——或者可能没有——差异。其他各种方法都没有过载
示例:

Derived1 d1;    
OtherClass* handlerInst = new OtherClass();
handlerInst->Add( &d1, &(Derived1::method1) );

Add(...)中,我想传递从基类派生的类类型的任何成员方法
这有可能吗?

编辑:

其思想是OtherClass是一个线程(而不是标准的c++线程)。其他类的某些代码(Derived1、derived2…)-不必具有公共基类-因此必须在该线程结束运行后才能运行。我希望看看我是否可以添加任何名称的方法。作为线程也与此无关。它可以是一个简单的类,当它结束方法时,它会运行其他类中的一些代码。

我假设这些函数也返回相同的类型(在本例中我使用了void)。

你没有说这些函数是否是在base中声明的虚拟函数的重写——你提到它们不是重载,但如果它们不是重写,那么base的存在在这里并没有真正的帮助。

如果它们确实存在于基地,那么你可以尝试以下方法:

#include <vector>
class OtherClass 
{ 
    using FunctionPtrType = void(Base::*)();
    std::vector<std::pair<Base*, FunctionPtrType>> m_Collection;
   public:

   void Add(Base* object, FunctionPtrType pMemberFunction)
   {
       m_Collection.emplace_back(object, pMemberFunction);
    }
   void CallAll()
   {
       for(auto item : m_Collection)
       {
           (item.first->*item.second)();
       }
    }
};

调用示例

Derived d1;
OtherClass holder;
holder.Add(&d1, &Base::Func);
holder.CallAll()

另一方面,如果函数不覆盖base中的虚拟函数,那么我有另一个涉及包装类的解决方案,如果上面的方法不适用,我可以发布它。

您可以存储绑定到其实例的成员函数,并使用std::is_base_of检查它们的类型是否正确。

在下面的示例中,每个方法存储两次,因此它们也将被调用两次。

// https://github.com/KubaO/stackoverflown/tree/master/questions/method-ptr-list-38718402
#include <cassert>
#include <vector>
#include <functional>
#include <type_traits>
struct Base {};
struct Derived : Base {
   int counter = 0;
   void method1() { counter += 10; }
   void method2() { counter += 100; }
};
template <typename B>
class HandlerList {
   using fun = std::function<void()>;
   std::vector<fun> m_handlers;
public:
   template <typename T,
             typename = typename std::enable_if<std::is_base_of<B, T>::value>::type>
   void add(T* instance, void(T::* member)()) {
      m_handlers.push_back(std::bind(member, instance));
   }
   template <typename T,
             typename = typename std::enable_if<std::is_base_of<B, T>::value>::type>
   void add(T* instance, std::initializer_list<void(T::*)()> members) {
      for (auto & member : members)
         add(instance, member);
   }
   void call() {
      for (auto const & handler : m_handlers)
         handler();
   }
};
int main()
{
   struct NotDerived { void foo() {} } nd;
   Derived d;
   HandlerList<Base> h;
   h.add(&d, &Derived::method1);
   h.add(&d, &Derived::method2);
   h.add(&d, { &Derived::method1, &Derived::method2 });
#if 0
   h.add(&nd, &NotDerived::foo); // this will fail to compile
#endif
   h.call();
   assert(d.counter == 220);
}