从另一个对象回调转换和设置

Callback casting and set from another object

我只是想问问我的方法是错误的还是一个是正确的方法可以做到。

在项目中,我有一个hal和几个基于Base的Dir。 当我创建一些目录时,我将 hal 传递给它,因为每个目录都以自己的方式使用它。 每个人也以自己的方式对大厅中的事件做出反应。所以我想使用回调机制。我有一段时间我只有一个特定的控制器,我更改它、删除并创建另一个,此时我必须连接回调。 我用一种目录类型创建了一个解决方案,它工作正常。 但是当我想使用几个不同的目录时选择什么路径,我可以转换为 base 并在 Hal 中使用 base 是这样的吗:

class Base;

class Hal
{
  public:
  void set_callback(void (Base::*callback)(int), Base* base)
  {
    m_callback = callback;
    m_base = base;
  }
  void fun()
  {
    (m_base->*m_callback)(some_int);
  }

  private:
  Base* m_base;
  void (Base::*m_callback)(int);
};
#include "Hal.h"

class Base
{
  public:
  virtual void active() = 0;
  virtual void foo(int variable) = 0;
};
class Dir : public Base
{
  public:
  Dir(Hal& hal)
  : m_hal(hal)
  {}
  void active()
  {    
    auto callback = &Dir::foo;
    //add some casting?
    m_hal.set_callback(callback, this);
  }
  void foo(int variable)
  {
    // some code
  }

  private:
  Hal& m_hal;
};

也许我应该添加一个单独的 class 来路由此类回调?或者使用不同的机制?不幸的是,我在这个项目中没有可用的功能库 /:

一个 class 的成员函数指针不能转换为另一个 class 的成员函数指针,即使这些函数看起来兼容。您可以使用抽象层近似此转换,例如使用 std::function<void(Base*, int)>,但使用强制转换无法实现。

但是,成员函数指针尊重多态性。实际调用的函数将取决于调用它的对象的动态类型。

你只需要传&Bar::foo,也就是virtual。由于它将使用 Dir 调用,因此将使用 Dir::foo 覆盖。

更改为 m_hal.set_callback(&Bar::foo, this); 应该会如您所愿。

实例:https://godbolt.org/z/fd8hsbanv