我有一个类,它应该包含指向各种类的方法的指针并通过它调用它们。
像here这样的东西,但有一个小的 - 或者可能没有区别。那些各种其他方法都不会超载 示例:
Derived1 d1;
OtherClass* handlerInst = new OtherClass();
handlerInst->Add( &d1, &(Derived1::method1) );
在Add(...)
中我想传递从base派生的类类型的成员方法
这有可能吗?
这个想法是OtherClass是一个线程(不是标准的c ++线程)。其他类的一些代码(Derived1,derived2 ...) - 不必具有公共基类 - 因此必须在此线程结束其运行后才能运行。 我希望看看我是否可以添加任何名称的方法。 也是一个线程与此无关。它可以是一个简单的类,当它结束它的方法时,它会从其他类运行一些代码。
答案 0 :(得分:1)
我假设这些函数也返回相同的类型(在这个例子中,我已经使用了void)。
你不能说这些函数是否覆盖了在base中声明的虚函数 - 你提到它们不是重载,但是如果它们没有覆盖那么base的存在对这里没有帮助。 / p>
如果它们确实存在于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中的虚函数,那么我有另一个涉及包装类的解决方案,如果以上内容对你不起作用我可以发布。
答案 1 :(得分:0)
您可以存储绑定到其实例的成员函数,并使用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);
}