'which is better, dynamic binding or interface class when implementing a callback interface

In my case, I have to give a callback interface, there're 2 solutions:

case 1, interface class

class interface {
public:
    virtual void callback(param_t params);
};

case 2:

class dynamic_binding_interface {
public:
    std::function<void(param_t params)> callback;
};

what I'm worried about case 2 is:

  1. in my case, I don't need to change the implementation of callback, so it's acctually one-time bind
  2. it could be difficult to debug, since std::function cannot hold param names

the point is I'm worried about case 1 is:

  1. complicated inheritance in the future
  2. I must create a new class to implement interface each time

so, any suggestions? thanks in advance



Solution 1:[1]

Using a callback via an abstract class (interface), and using std::function have each advantages and disadvantages. It's also a matter of opinion and preference.

Having said that, I'll try to demonstrate 2 extreme cases where I believe it is better suited to use this or the other.

Using an interface:

The main advantage of using an interface, is that you can have all the callback in one place. If you some server class with some methods (the incoming interface), it's convenient to think of the callbacks (where the server notifies of certain events) as an out going interface and treat them as one entity. It also allows, with the usage of pure virtual methods, to force the client to implement them (and therefore be aware of the various notifications).

Typical example:

struct SomeServerCallback
{
    virtual void NotifyX() = 0;
    virtual void NotifyY() = 0;
    virtual void NotifyZ() = 0;
    // ...
};

class SomeServer
{
public:
    SomeServer(SomeServerCallback * pCallback) : m_pCallback(pCallback) {}
    void Do1() { /*...*/ }
    void Do2() { /*...*/ }
    // ...
protected:
    SomeServerCallback * m_pCallback;
};

Using a std::function:

On the other hand, if you have another server class that does not need to notify the client of various events, but does need a callback for printing messages, it can be more convenient to use std::function, rather then define an interface and force clients to derive from it. It allows the client to choose how to define the callback (using a lambda, std::bind with a class method etc.).

Typical example for this case:

#include <functional>
#include <string>

class SomeOtherServer
{
public:
    using MyPrintCallback = std::function<void(std::string const&)>;
    SomeOtherServer(MyPrintCallback printCallback) : m_printCallback(printCallback) {}
    void Do1() { /*...*/ }
    void Do2() { /*...*/ }
    // ...
protected:
    MyPrintCallback m_printCallback;
};

Using these solutions involves different overheads (performance-wise and others).
But I believe none of them is in principle prefered over the other.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1