我是C++的新手,我在一个项目上苦苦挣扎,需要在不同的类实例之间传递对回调方法的引用。我知道对于C++初学者来说,这个主题是一个非常普遍的问题。我了解成员函数指针与“标准”函数指针不同,但是我找不到能解决我的特定问题的任何帖子(但这可能是因为鉴于我缺乏C++的经验,所以我不理解所提供的答案)。

我尝试开发的系统基于:

  • ControllerManager的类(单例)
  • Controller 基类
  • 从Controller类
  • 继承的一些特定的Controller类( FanController LighController 等)

    我想做的是从说一个 FanController 实例到调用 ControllerManager 类的 addCallback 方法。此方法将指向FanController的任何公共(public)方法的指针作为参数,以便ControllerManager以后可以对该方法进行回调(我必须指定ControllerManager包括Controller类的定义,但对此方法一无所知FanController类)

    到目前为止,我还没有找到任何可行的解决方案,我设法获得的唯一解决方法是非常差的解决方法(为简单起见,仅指示了相关方法):
    class Controller {
    
    public:
        virtual void callback();
    };
    
    
    class FanController:Controller {
    
    public:
        virtual void callback();
    };
    
    
    class ControllerManager
    {
    private:
        static ControllerManager *_instance;
        Controller *_controller;
    
    public:
    
        void addCallback(Controller * controller)
        {
            _controller = controller;
        }
    
        static void periodicCallback()
        {
           _instance->_controller->callback();
        }
    };
    

    在运行时,FanController实例为ControllerManager单例提供了自己的引用:
    ControllerManager::getInstance()->addController(this);
    

    并且ControllerManager可以调用FanController实例的回调方法:
     _instance->_controller->callback();
    

    由于仅允许调用由父 Controller 类声明的方法,因此此解决方法非常有限。

    我要实现的是一个系统,允许特定 Controller 向ControllerManager提供其成员方法(在Controller类中不存在)的引用,以便可以调用这些方法。

    如果有人可以帮助我,我先感谢他/她。

    最佳答案

    解决此问题的现代方法是在lambda中松开方法的绑定(bind)。

    #include <functional>
    #include <vector>
    
    
    class Controller {
      std::vector<std::function<void()>> callbacks_;
    
    public:
      void addCallback(std::function<void()> cb) {
          callbacks_.push_back(std::move(cb));
      }
    
      void periodicCallback() {
         for(const auto& cb : callbacks_) {
           cb();
         }
      }
    };
    
    
    class Fan {
    public:
      void whatever() {}
    
      void register_in_controller(Controller* tgt) {
        tgt->addCallback([this]{whatever();});
      }
    };
    

    10-08 18:08