【问题标题】:How to implement callbacks with interface如何使用接口实现回调
【发布时间】:2012-09-05 10:44:42
【问题描述】:

我有一个需要更多回调的类.. 我正在尝试使用接口来实现它们:

class CallbacksInterface
{
public:
     virtual bool mycallback1() = 0;
     virtual bool mycallback2() = 0;
     virtual bool mycallback3() = 0;
};

Class BusImplementation{
public:
    addRequest(bool (CallbacksInterface::*callback)());

}

回调是addRequest()方法的参数,定义为指向接口方法的指针。 所以我想添加请求..

//class with callbacks
class Main:CallbacksInterface{
public:
      bool mycallback1(){..};
      bool mycallback2(){..};
      bool mycallback3(){..};
      //.. 
}

BusImplemantation bus;
Main main;   

bus.addRequest(main.mycallback1);          
bus.addRequest(main.mycallback2);
bus.addRequest(main.mycallback3);

但我无法将回调传递给我的 BusImplementation 类

error: argument of type 'bool (Main::)()' does not match 'bool (CallbacksInterface::*)()'

我认为有一个使用模板的解决方案,但我正在编写嵌入式设备并且我的编译器是有限的。

【问题讨论】:

  • 拥有一个代表单个函数的回调接口,并将指针传递给它的不同实现不是更简单吗?或者更好的是,使用std::functions?
  • 如果你使用公共继承有帮助吗,即class Main: public CallbacksInterface
  • 以防万一您使用实际软件项目中的类型名称 - BusImplemantation 中有一个错字。

标签: c++ interface callback


【解决方案1】:

我也强烈建议使用抽象接口。但是,如果您出于某种原因真的想要原始方法,则需要这样的东西:

void addRequest(bool (CallbacksInterface::*callback)(), CallbacksInterface* pTarget) {...}
...
bus.addRequest(&CallbacksInterface::mycallback1, &main); 
// ! Not &Main::mycallback1 - that wouldn't compile
...
// calling a callback
(pTarget->*callback)();

【讨论】:

    【解决方案2】:

    更简单的方法是定义一个表示函数的接口类型:

    struct ICallback
    {
      virtual bool operator()() const = 0;
    };
    

    并根据需要多次实施:

    struct Foo : ICallback
    {
      virtual bool operator()() const { return true;}
    };
    
    struct Bar : ICallback
    {
      virtual bool operator()() const { return false;}
    };
    

    那么你的总线实现可以采用回调接口:

    class BusImplemantation{
    public:
        void addRequest(const ICallback* callback) { .... }
    };
    

    然后

    BusImplemantation bus;
    Foo foo;  // can be called: bool b = foo();
    Bar bar;   // can be called: bool b = bar();
    
    bus.addRequest(&foo);          
    bus.addRequest(&bar);
    

    您还可以使用std::function 进行调查,并完全避免使用通用接口。

    【讨论】:

    • 看起来很有趣,我必须尝试一下!这个 operator() 有特定的含义吗?它对我来说是新的。谢谢
    • @Meloun operator() 使实例“可调用”。我在代码中添加了一些 cmets。如果你有ICallback*,你可以这样调用操作员:pCakkBack->operator()();
    • (*pCallBack)(); 怎么样?对我来说似乎更好。
    • 缺点:如果回调在某个类中,你不能在回调中访问这个类和成员。如果回调不是类,而是您可以的唯一方法。 (内部类与方法)
    • @Meloun 为什么不能调用类成员并在回调中访问数据?我看不到。
    猜你喜欢
    • 2021-07-21
    • 2022-01-13
    • 2011-10-08
    • 1970-01-01
    • 2014-06-17
    • 2015-02-05
    • 1970-01-01
    • 2014-01-13
    • 1970-01-01
    相关资源
    最近更新 更多