Prefer well defined interfaces over callbacks
The problem with std::function
(previously boost::function
) is that most of the time you need to have a callback to a class method, and therefore need to bind this
to the function object. However in the calling code, you have no way to know if this
is still around. In fact, you have no idea that there even is a this
because bind has molded the signature of the calling function into what the caller requires.
This can naturally cause weird crashes as the callback attempts to fire into methods for classes that no longer exist.
You can, of course use shared_from_this
and bind a shared_ptr to a callback, but then your instance may never go away. The person that has a callback to you now participates in your ownership without them even knowing about it. You probably want more predictable ownership and destruction.
Another problem, even if you can get the callback to work fine, is with callbacks, the code can be too decoupled. The relationships between objects can be so difficult to ascertain that the code readability becomes decreased. Interfaces, however, provide a good compromise between an appropriate level of decoupling with a clearly specified relationship as defined be the interface's contract. You can also more clearly specify, in this relationship, issues like who owns whom, destrcution order, etc.
An additional problem with std::function
is that many debuggers do not support them well. In VS2008 and boost functions, you have to step through about 7 layers to get to your function. Even if all other things being equal a callback was the best choice, the sheer annoyance and time wasted accidentally stepping over the target of std::function
is reason enough to avoid it. Inheritance is a core feature of the language, and stepping into an overridden method of an interface is instantaneous.
Lastly I'll just add we don't have delegates in C++. Delegates in C# are a core part of the language, just like inheritance is in C++ and C#. We have a std library feature which IMO is one layer removed from a core language functionality. So its not going to be as tightly integrated with other core features of the language. It instead helps formalize the idea of function objects that have been a C++ idiom for a good while now.