Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I basically do not understand clang's -Wweak-vtables. Here is what I observed so far:

Case one: (triggers the warning)

class A {
    public:
    virtual ~A(){}        
};

class B : public A {
    public:
    virtual ~B(){}
};

int main(){}

Case two: (Does not trigger warning)

class A {
    public:
    virtual ~A(){}        
};   

int main(){}

Case three: (Does not trigger warning)

class A {
    public:
    virtual ~A();

};

A::~A(){}

class B : public A {
    public:
    virtual ~B(){}
};

int main(){}

Case four: (Triggers warning)

class A {
    public:
    virtual ~A(){}
    virtual void fun(){}        
};    

class B : public A {
    public:
    virtual ~B(){}
};

int main(){}

Case five: (Does not trigger warning)

class A {
    public:
    virtual ~A(){}
    virtual void fun();      
};    

class B : public A {
    public:
    virtual ~B(){}
};

int main(){}

Case six: (Does not trigger warning)

class A {
    public:
    virtual ~A(){}
    virtual void fun(){}
};    

class B : public A {};

int main(){}

Case seven: (Does not trigger warning)

class A {
    public:
    virtual ~A(){}
    virtual void fun(){}
};    

class B : public A {
    public:
    virtual void fun(){}
};

int main(){}

The exact warning is

warning: 'A' has no out-of-line virtual method definitions; its vtable 
will be emitted in every translation unit [-Wweak-vtables]

So apparently, if I do not declare a non-inline virtual function in a class, it causes some kind of problem if and only if I derive from it and the derived class has a virtual destructor.

Questions:

  1. Why is this a problem?
  2. Why does this get fixed by declaring a virtual function? (Warning speaks of definitions)
  3. Why does the warning not occur when I do not derive from the class?
  4. Why does the warning not occur when the derived class does not have a virtual destructor?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
253 views
Welcome To Ask or Share your Answers For Others

1 Answer

If all of a class's virtual methods are inline, the compiler has no way to select a translation unit in which to place a single shared copy of the vtable — instead, a copy of the vtable has to be placed in each object file that needs it. On many platforms the linker is able to unify these multiple copies, either by discarding duplicate definitions or by mapping all references to one copy, so this is only a warning.

Implementing a virtual function out-of-line enables the compiler to select the translation unit that implements that out-of-line method as a "home" for the class's implementation details, and places the single shared copy of the vtable in the same translation unit. If multiple methods are out-of-line, an arbitrary choice of method may be made by the compiler so long as that choice is determined only by the class's declaration; for example, GCC chooses the first non-inline method in declaration order.

If you don't override any method of a class, the virtual keyword has no observable effect, so there's no need for the compiler to emit a vtable for the class. If you do not derive from A, or if you fail to declare a derived class's destructor virtual, there are no overridden methods in A and thus A's vtable is omitted. If you declare an additional out-of-line virtual method to suppress the warning and also do something that overrides a method in A, the implementation of the non-inline virtual (and its accompanying copy of the vtable) needs to be supplied in a linked translation unit, otherwise linking will fail because the vtable is missing.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...