vfunc(and dtor) is called in both foo.cpp and main.cpp polymorphically(not inlined), which means it's defined twice in the entire program,
first of all: calling does not mean definition. So the function calls do not tell you wether the ODR is violated.
so it violates the ODR, isn't it? How does it compiles(link) ?
It compiles, because member functions defined inside a class definition are implicitly declared inline and therefore don't violate the ODR. That applies for both vfunc
definitions as well as for the dtors, so you are good here.
Note: There is a difference between an function declared inline
(explicitly or implicitly) and a function that actually gets inlined. The compiler's decision to inline a function once could be influenced by the inline
keyword, but it was and is only a hint. These days optimizers can predict better than any human when and when not inlining is a good choice, so the compiler can ignore that hint whenever it sees fit, and it can inline functions that have not been declared inline. So with modern compilers, inline
is just a means to obey the ODR for functions, that are not declared inline
implicitly.
Update: So in your case, the function is declared inline implicitly, the definition is included in two translation units (the two .cpp's) and it does not get inlined by the compiler. In this case, the linker will see the symbol for the function twice, but it will not complain about multiple symbols because of the inline declaration.