3

I have a class which needs more callbacks.. I am trying to implement them with an interface:

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

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

}

Callback is parameter for addRequest() method and is defined as pointer to interface method. So I want to add request..

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

But I cant pass a callback into my BusImplemantation class

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

I think there is a solution with templates, but I am programming embedded devices and my compiler is limited.

Meloun
  • 13,601
  • 17
  • 64
  • 93
  • Wouldn't it be simpler to have a callback interface representing a single function, and pass pointers to different implementations of that? Or even better, use ``std::functions``? – juanchopanza Sep 12 '12 at 12:10
  • Does it help if you use public inheritance, i.e. `class Main: public CallbacksInterface`? – Frerich Raabe Sep 12 '12 at 13:17
  • Just in case you're using the type names from your actual software project - there's a typo in `BusImplemantation`. – Frerich Raabe Sep 12 '12 at 13:19

2 Answers2

9

A simpler approach would be to define a single interface type representing a function:

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

and implement it as many times as necessary:

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

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

then your bus implementation can take callback interfaces:

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

then

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

bus.addRequest(&foo);          
bus.addRequest(&bar);

You could also investigate using std::function and avoiding the common interface altogether.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • seems interesting, I have to try it! This operator() has specific meaning? Its new for me. thanks – Meloun Sep 12 '12 at 13:21
  • 2
    @Meloun the ``operator()`` makes an instance "callable". I added some comments in the code. If you have an ``ICallback*``, you can call the operator like this: ``pCakkBack->operator()();`` – juanchopanza Sep 12 '12 at 13:31
  • 1
    What about **(*pCallBack)();** ? seems nicer for me. – Meloun Sep 13 '12 at 08:22
  • disadvantage: If callback is in some class, you cant within callback access to this class and members. If callback would be not class, but only method you can. (inner class vs. method) – Meloun Sep 13 '12 at 08:29
  • @Meloun why can't you call class members and access data within the callback? I can't see it. – juanchopanza Sep 13 '12 at 08:50
  • **to juanchopanza:** http://pastebin.com/XHgBiAQx If callback would be only method you can access to myvar. – Meloun Sep 13 '12 at 11:11
1

I also strongly suggest going with an abstract interface. However, if you really want the original approach for some reason, you need something like this:

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