struct A
{
virtual void foo(); // unused and unimplemented
virtual void bar () {}
};
int main ()
{
A obj; // ok
obj.bar(); // <-- added this edition
A* pm = (A*)malloc(sizeof(A)); // ok
A* pn = new A; // linker error
}
For objects on stack it works fine. But for allocation on heap with new (not malloc), it gives linker error:
undefined reference to `vtable for A'
Firstly, this code is not compilable, since in C++
void *cannot be implicitly converted toA *. An explicit cast is required.Secondly, the example with
mallocis completely irrelevant.mallocallocates raw memory, with has absolutely no relation to any specific types. In this casemallocknows noting about anyAand it does not create an object of typeA.For this reasons the real example for this question should look as follows
And the question is why the first declaration produces no liker error while the second one does.
From the formal point of view, your program is invalid because it violates formal requirements of C++ language (specifically ODR). In practice, both declarations could or should produce the same error, since in both cases the object formally requires a pointer to VMT. In this case VMT cannot be created, since some functions are undefined. However, the first declaration simply slips through just because the compiler was able to optimize-out all references to VMT for the first declaration (and not for the second). It is also quite possible that the compiler was able to optimize-out the whole
objobject, since it is not referenced anywhere else.In GCC (since you appear to be using GCC) it is easy to trigger the same error for the first declaration as well
The above code will produce the same linker error in GCC even though the undefined function
foois still not used in this code.In other words, it is simply a matter of adding sufficient amount of code to make the compiler believe that the object’s VMT is needed. The difference in behavior between the declarations has nothing to do with C++ language in this case. It is just an implementation issue specific to your compiler.