Clang -Wweak-vtables and pure abstract class

后端 未结 1 567
广开言路
广开言路 2021-02-08 11:18

With regard to previous questions on this topic:

This a follow up of the question that I\'ve asked recently: clang: no out-of-line virtual method defini

1条回答
  •  鱼传尺愫
    2021-02-08 11:24

    A class with virtual methods always needs to emit a vtable. The compiler needs an indication of where to store the vtable - usually in the object that implements its first function.

    What's so special about pure abstract classes? Since they have no methods, the compiler has to output a vtable in every translation unit so each translation unit can refer to the pure abstract base type. That's what the warning is telling you.

    You might care, for example, if you want to avoid duplicating that memory in a very low memory environment, or if you go looking at the objects and wonder why there are multiple copies of the vtable around the place.

    In any case, the fact that you can take a polymorphic pointer to an A object means that the compiler has to emit some information about that type — the vtable.

    Option 1: implement a virtual method, such as the destructor

    My preference when creating an abstract base class is to provide an out-of-line virtual destructor; ie. implement A::~A() in the .cpp file. The downside of a user-declared virtual destructor is that it implicitly deletes the automatically-generated copy- and move-constructors & operators, so you end up needing to redeclare them. According to the rule of five, this results in a base class like this:

    A.h:

    class A {
    public:
        A() = default;
    
        A(const A&) = default;
        A(A&&) = default;
        A& operator=(const A&) = default;
        A& operator=(A&&) = default;
        virtual ~A();
    
        virtual void doSomething() = 0;
    };
    

    A.cpp:

    A::~A()
    {}
    

    It's technically no longer a pure-abstract base class, but it is functionally identical. You get safe destruction by base pointer, it still allows inherited classes to be copy- and move-constructed, and you avoid duplicate vtables in your binary.

    Option 2: disable the warning

    You can disable the warning for that block with Clang's diagnostic pragmas if you like:

    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wweak-vtables"
    class A {
    public:
        virtual void doSomething() = 0;
        virtual ~A() = 0;
    };
    #pragma clang diagnostic pop
    

    That's your dilemma: either make the class non-pure-abstract, or turn off the warning. Depending on your requirements you might prefer one or the other, but as with all warnings you should carefully consider it.

    0 讨论(0)
提交回复
热议问题