Why does this virtual destructor trigger an unresolved external?

前端 未结 7 1560
情书的邮戳
情书的邮戳 2021-02-19 03:43

Consider the following:

In X.h:

class X
{
    X();
    virtual ~X();
};

X.cpp:

#inclu         


        
7条回答
  •  攒了一身酷
    2021-02-19 04:05

    The answer to your first question,

    What causes the unresolved external in the linker when the .dtor is virtual or when the .ctor isn't inlined?

    ...is, quite simply, that you don't have a definition for the destructor.

    Now your second question is somewhat more interesting:

    why do I not get an unresolved external if I make the destructor non-virtual, or if I inline the constructor?

    And the reason is because your compiler didn't need X's destructor since you never instantiated X, so it threw your whole class away. If you try to compile this program, you will get an unresolved external:

    class X
    {
    public:
        X();
         ~X();
    };
    
    X::X() {};
    
    int main()
    {
        X x;
        return 0;
    }
    

    But if you comment out X x; it will compile just fine, as you have observed.

    Now let's come back around to why it won't compile if the destructor if virtual. I'm speculating here, but I believe the reason is because, since you have a virtual destructor, X is now a polymorphic class. In order to lay-out polymorphic classes in memory, compilers that implement polymorphism using a vtable need the adresses to every virtual function. You haven't implemented X::~X, so an unresolved external results.

    Why doesn't the compiler just throw X away as it did when X was not a polymorphic class? More speculation here. But I expect the reason is because even if you haven't directly instantiated X, it can't be sure that nowhere in your code does an X live, masqerading as something else. For an example, consider an abstract base class. In this case, you'll never instantiate Base directly and the code for Derived might be in a totally seperate translation unit. So when the compiler gets to this polymorphic class, it can't discard it even if it doesn't know you instantiated it.

提交回复
热议问题