Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a virtual function with only a declaration result in a compiler error?

Tags:

c++

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.

Question

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?

like image 336
Alcott Avatar asked Jan 14 '13 10:01

Alcott


4 Answers

This is strictly up to the compiler. No diagnostic is required for either case.

10.3 Virtual functions [class.virtual]

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).

like image 134
Luchian Grigore Avatar answered Sep 26 '22 21:09

Luchian Grigore


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.

like image 41
Benoit Avatar answered Sep 24 '22 21:09

Benoit


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.

like image 35
Ram Avatar answered Sep 26 '22 21:09

Ram


A virtual function declared in a class shall be defined, or declared pure in that class, or both(C++03 Standard).

like image 43
Hui Zheng Avatar answered Sep 26 '22 21:09

Hui Zheng