As others have said, it is undefined behavior. What is (probably) happening, however, is that in the first case (the call in the constructor), the compiler knows the dynamic type of the object (since it is always the type being constructed), and so generates the call exactly as it would for calling any non-virtual function. (If you had failed to provide a definition, I imagine that the linker would have complained.) In the second case, you call the function from within another function. At that point, the compiler has no way of knowing the dynamic type the object will have at runtime; the function could have been called on a fully constructed object, perhaps of a derived type not even present in this source file. Since the compiler cannot determine statically the dynamic type the object will have at runtime, it must generate a call through the virtual function table (or whatever method it uses to resolve dynamic dispatch, but VS, like everyone else I know, uses a vptr to a vtable). Since calling a pure virtual function in this manner is undefined behavior, the compiler puts a pointer to an error handling routine in the vtable.
Note that in this case, the compiler could have seen that the
call in the constructor of Base
would resolve in a manner
which causes undefined behavior, and generated code which would
have triggered the error. Or... since all of the virtual
functions of Base
are pure virtual, the compiler could have
known that the cannot be called during construction, and not
even bothered to create a separate vtable for Base
, perhaps
initializing the vptr to point to the vtable of Derived
before
calling the constructor of Base
. You can't count on anything
such cases.