如何使用接口实现回调功能

3

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

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 更好。 - juanchopanza
如果使用公共继承,即class Main: public CallbacksInterface,是否有帮助? - Frerich Raabe
如果您正在使用实际软件项目中的类型名称,请注意BusImplemantation中有一个拼写错误。 - Frerich Raabe
2个回答

9

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

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
2
@Meloun,“operator()”使一个实例“可调用”。我在代码中添加了一些注释。如果你有一个“ICallback*”,你可以这样调用操作符:“pCakkBack->operator()();”。 - juanchopanza
1
那么 **(pCallBack)();* 呢?对我来说更好看。 - Meloun
缺点:如果回调函数在某个类中,你无法在回调函数内部访问该类和其成员。如果回调函数不是类而只是方法,则可以访问。(内部类 vs. 方法) - Meloun
@Meloun为什么你不能在回调函数中调用类成员并访问数据?我看不到。 - juanchopanza
给juanchopanza:http://pastebin.com/XHgBiAQx 如果回调函数是您可以访问myvar的唯一方法。 - Meloun

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)();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接