The virtual keyword in c++ is more of a compiler optimization and less of a design decision. C++ doesn't want everyone paying the overhead of virtual function calls like other languages
Of course these days with LTO the whole performance space is somewhat blurred since de-virtualisation can happen across whole applications at link time, and so the presumed performance cost can disappear (even if it wasn't actually a performance issue in reality). It's tough to create hard and fast rules in this case.