Sunday 20 March 2016

c++ - Why does this virtual destructor trigger an unresolved external?



Consider the following:




In X.h:



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



X.cpp:



#include "X.h"

X::X()
{}


Try to build this (I'm using a .dll target to avoid an error on the missing main, and I'm using Visual Studio 2010):





Error 1 error LNK2001: unresolved external symbol "private: virtual __thiscall X::~X(void)" (??1X@@EAE@XZ)




Small modifications result in a successful build, however:



X.h:



class X
{

inline X(); // Now inlined, and everything builds
virtual ~X();
};


or



X.h:



class X

{
X();
~X(); // No longer virtual, and everything builds
};


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



EDIT:




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


Answer



Situation 1:



You have the code for the constructor.
So it builds the constructor into the object file. The constructor needs the address of the destructor to put into the virtual table because it can not find it the constructor can not be built.



Situation 2: (inline constructor)



The compiler decides it does not need to build the constructor (as it will be inlined).
As such it does not plant any code and therefore does not need the address of the destructor.




If you instanciate an object of type X it will again complain.



Situation 3: (non virtual destructor)



You don't need the address of the destructor to build the constructor.
So it does not complain.



It will complain if you instantiate an object of type X.


No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...