The C++ standard is written in such a way that a vtable as the first member of a polymorphic class instance is
the obvious way to satisfy the standard's demands. I don't think there is any mainstream C++ implementation that doesn't use vtables, although some older C++ compilers used a slightly different layout.
The fact that inside a single CU an optimizing compiler can determine the targets of polymorphic dispatch statically is unrelated, because most usage scenarios (more than one CU, external modules) preclude such optimizations anyway.
vtables aren't undefined, they are implementation defined and part of the C++ ABI. As soon as you expose something through the C++ ABI the compiler has to use the ABI's definitions.