this mean that you can sacrifice some "tidiness" to gain speed (code writing or runtime speed).
The alternative to dynamic polymorphism is not necessarily faster. Consider
std::function, it needs to dispatch dynamically too, either through virtual functions or function pointers. Static polymorphism can be faster, but it requires knowledge at compile time. By the way, the main reason I use modern C++ features is not speed, rather the possibility to apply powerful and expressive concepts.
Also, I don't really think it's less tidy. Of course, functionals are more difficult to understand initially, but once this is done, they can simplify things a lot (less code and fewer classes to maintain). Concerning debugging, you can track a callback the same way as a called virtual function -- only that the callstack may contain some levels of the
std::function implementation itself, but they can be skipped.
I think what you say about Java collections is wrong, those design flaws comes from first versions of the language and not from some lack of features.
They resulted to one side because the language lacked features (initially there were no generics, it's still possible to use untyped collections) and still lacks (global functions like the STL algorithms are not possible, instead much functionality is duplicated for each collection type; because of no
const, new unmodifiable objects must be created). Also, there are severe design flaws resulting from bad OOP and LSP understanding (
Stack inherits
Vector).
Interfaces are nice in many situations, but they have some problems: They cannot contain state or implementation, so if multiple classes implement the same interface and have partially the same data or functions, code duplication is necessary. Also, the only way to abstract from multiple classes is to let them implement the same interface; if you cannot change the classes, you're lost (meaning you have to write further adapter classes). The mere existence of
UnsupportedOperationException shows the limits of interfaces pretty well, it introduces weakly typed elements. At least generics improve the situation slightly, but it's well visible that they are put on top of the existing language and do not integrate very well.
To sum up, Java is a good example to show the problems of using class hierarchies as the primary way of abstraction. The whole discussion is not as simple as "strict OOP = better maintenance but worse speed", a lot of unconventional C++ features improve also maintenance and debugging.