【问题标题】:C++ multiple callback member functions from different classes without std and boost来自不同类的C++多个回调成员函数,没有std和boost
【发布时间】:2016-05-09 05:46:47
【问题描述】:

我是 C++ 新手,我不想使用任何库,因为我想真正了解内部发生的事情。 此外,我尝试使我的库使用率尽可能低(以提高性能并)使其尽可能独立于平台(不导出库)。
所以总而言之,我不想使用 std 或 boost 来解决这个问题。

我的问题:

我有一个 EventHandler,它有一个函数:

template<class T> void EventHandler::SetCallbackFunction(T* obj, void (T::*mem_fkt)(void));

我必须保存对象和函数以便稍后调用它。
有两种可能:

  • EventHandler 作为模板类(和 typedef)
  • void* -> 但要调用该函数,我需要将其转换回来,为此我需要类名:/

为什么这些不起作用: - EventHandler 不能是模板类,因为它需要处理多个类.. - void* -> 我不知道如何保存类名以便以后转换

我该怎么做?
(或者还有其他方法吗?也许是一种保存类名以供以后转换的方法?)

编辑:
此外,我可能需要为每个类注册多个回调函数,因此接口并不是一个真正的选择。

class A {
 public:
   void CallbackFktForEventHandler();
   void CallbackFktForAnimationHandler();
   etc...
};

而且我知道你可以基于这样的方法来解决它:

class A{
  public:
    void Callback();
    static void CallbackStatic(void* self){
      static_cast<A*>->CallBack();
    };
};

但这对我的口味限制太多了。

【问题讨论】:

  • 是什么让您觉得避免使用库对性能有好处?
  • 重新编辑:没有什么能阻止你包装多个成员函数:auto f = wrap(a, &amp;A::CallbackFktForEventHandler); auto g = wrap(a, &amp;A::CallbackFktForAnimationHandler);

标签: c++ templates c++11 callback classname


【解决方案1】:

您可以使用类型擦除。通过实例化实现非模板虚拟接口的类模板,您可以有效地保存obj 的类型。这基本上就是std::function 的实现方式,所以您只是在编写自己的std::function 的基本版本。

struct ICallback
{
    virtual void call() = 0;
};

template <class T>
struct Callback : public ICallback
{
    virtual void call() override { (m_obj->*m_func)(); }
    Callback(T *obj, void (T::*func)()) : m_obj(obj), m_func(func) {}
    T *m_obj;
    void (T::*m_func)();
};

template <class T>
std::unique_ptr<ICallback> wrap(T *obj, void (T::*func)())
{
    return std::make_unique<Callback<T>>(obj, func);
}

如果您不想使用std::unique_ptr,您可以自己滚动或使用邪恶的原始拥有指针。

【讨论】:

  • 好的,非常感谢,我会研究一下这种方法(就像我说我是 c++ 新手)
【解决方案2】:

你可以试试这个:

创建一个只有一个函数的(纯虚拟)基类call()

class Function{
  virtual void call()=0;
}

创建一个模板类,该类存储一个函数指针和一个对象,并使其继承自Function

template<typename T>
class TemplatedFunction{
  void (T::*m_fkt)(void);
  T* m_obj;

  TemplatedFunction(T* obj, void (T::*fkt)(void)):m_fkt(fkt),m_obj(obj){}

  void call{
    (m_obj->*m_fkt)();
  }
}

然后将指向Function 的指针存储在您的事件处理程序中,然后使用Function-&gt;call()

在线试用:http://ideone.com/3Hu5pw

但是,如果您至少使用标准库,您的生活会轻松很多。基本上我会使用 std::bind 将你的对象和你的成员函数绑定到一个函数 void()(void) 中,然后将这些对象存储在一个 std::vector 中。

编辑:Oktalist 更快 ;)

【讨论】:

  • 感谢在线示例!我想为你的帖子投票,但我没有足够的声誉。
猜你喜欢
  • 2015-06-15
  • 2012-03-04
  • 1970-01-01
  • 2011-01-01
  • 2016-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-13
相关资源
最近更新 更多