I have this class,
class Base {
public:
void foo();
};
int main()
{
Base b;
}
main
will compile without any error, although foo()
has no definition. But b.foo();
will result in a compile error.
Moreover, even for constructor
and operator=
, I can just declare them without defining them, it'll compile as long as I don't trigger them.
Again, I add a virtual function into Base
,
class Base {
public:
void foo();
virtual void bar(); // no defition is gonna be provided.
};
Now, main
cannot compile, instead I get an error:
undefined reference to vtable for Base
Well this confuses me a little bit, because previously, main
could compile as long as foo()
is not called, but now I add bar()
and it's not called at all.
Why doesn't it compile in this case?
This is strictly up to the compiler. No diagnostic is required for either case.
9 A
virtual
function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but no diagnostic is required (3.2). [emphasis mine]
To understand why this happens though, let's have a look at how it works.
Each translation unit generates an object file, each object file with exports (symbols it exported) and imports (symbols it wants).
The first example is simple - the imports only require foo
when it is used. There's no reason for the linker to look for the symbol, so it doesn't.
The second one, with the virtual
method, is a bit more complicated. Most compilers (if not all) required valid virtual function tables. That means that at link time, all classes that declared non-pure virtual methods would have to have those methods exported. This is stricter than the non-virtual
case because the implementation doesn't actually know whether the function is called or not (it could be called polymorphically).
First version can compile because the linker needn't search for the object foo
. It's used nowhere.
But when you create a virtual function, the construction of the vtable (for dynamic dispatch) needs an address for the function Base::bar
(it makes a reference to it) and therefore the linker needs to find an implementation of it.
When a polymorphic object (instance of a class with at least one virtual function) is created, it has to have a virtual table pointer that points to the virtual table. Each polymorphic class will have a virtual table that is constructed once. It is up to the implementation of the compiler to allow the virtual table to be incomplete. This table is populated based on virtual function definition.
If any virtual function is not implemented and the function is not pure virtual then some compilers give a compiler error as the virtual table is incomplete.
In the case of a simple (non-virtual) function, the function declaration will be ignored if it is never used. Even if it is used, we get a linker error and not compiler error.
A virtual function declared in a class shall be defined, or declared pure in that class, or both(C++03 Standard).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With