Search code examples
c++functionclassmemberdesign-decisions

How can a function ask its caller class to invoke one of its methods?


I'm in a situation like this:

class Callee {
public:
  void request();
};

class Caller {
  void call() {
    Callee{}.request();
  }
  void invoke1(); // the implementation doesn't matter
  void invoke2(); // the implementation doesn't matter
  // more invoke()s
};

I want Callee::request() to request invocation of one of the Caller::invoke() member functions depending on the context which can be computed either in Callee::request() or in Caller::call():

void Callee::request() {
  // do stuff
  switch (context) {
    // request one of the invoke()s to be run immediately
  }
  // do more stuff
}

Which solutions would be elegant? I don't want (from most to least important):

  • Callee to know the definition of Caller;
  • use templates;
  • Callee to know the declaration of Caller;
  • Caller to choose an invoke() on its own;

It's OK if Callee::request() receives some arguments from the Caller.


Solution

  • There is a number of ways you can achieve this.

    • The most straightforward is to have Callee::request() return an enum value, which the Caller then does a switch on and invokes an appropriate function. This means that caller and callee will have to both know this enum.

    • Another way which is also in straightforward territory, though slightly more convoluted, is to pass a single function from the caller to the callee, which accepts that enum value as a parameter, so that by invoking this function the callee can indicate to the caller what it wants done. Again the caller can switch on that value and invoke either invoke1() or invoke2() or what have you.

    • Another way is to define an interface, (a class consisting of only pure virtual methods,) which contains invoke1() and invoke2() have the caller implement that interface, and pass that interface of itself to the callee, so that the callee can decide which function to call. In this case, caller and callee will need to both have knowledge of this new interface.

    • Another way is to pass the callee two pointers to functions, so that the callee can decide which one to call. This way the callee does not need to know anything, but it does not scale very well, because what if you have 50 different functions?