Gre*_*g D 15 c++ destructor virtual-functions unresolved-external
考虑以下:
在Xh:
class X
{
X();
virtual ~X();
};
Run Code Online (Sandbox Code Playgroud)
X.cpp:
#include "X.h"
X::X()
{}
Run Code Online (Sandbox Code Playgroud)
尝试构建这个(我使用的是.dll目标,以避免在丢失的main上出现错误,我正在使用Visual Studio 2010):
错误1错误LNK2001:未解析的外部符号"private:virtual __thiscall X :: ~X(void)"(?? 1X @@ EAE @ XZ)
然而,小的修改导致成功构建:
XH:
class X
{
inline X(); // Now inlined, and everything builds
virtual ~X();
};
Run Code Online (Sandbox Code Playgroud)
要么
XH:
class X
{
X();
~X(); // No longer virtual, and everything builds
};
Run Code Online (Sandbox Code Playgroud)
当.dtor是虚拟的或者.ctor没有内联时,是什么导致链接器中未解析的外部?
编辑:
或者,或许更有趣的是,如果我将析构函数设置为非虚拟,或者如果我内联构造函数,为什么我没有得到未解析的外部?
Mar*_*ork 22
你有构造函数的代码.
所以它将构造函数构建到目标文件中.构造函数需要将析构函数的地址放入虚拟表中,因为它无法找到构造函数无法构建的地址.
编译器决定它不需要构建构造函数(因为它将被内联).
因此它不会植入任何代码,因此不需要析构函数的地址.
如果您实例化X类型的对象,它将再次抱怨.
您不需要析构函数的地址来构建构造函数.
所以它没有抱怨.
如果你实例化一个X类型的对象,它会抱怨.
您需要为虚拟析构函数提供主体:
class X
{
X();
virtual ~X() {}
};
Run Code Online (Sandbox Code Playgroud)
在C++函数中,当且仅当它们在您的程序中使用时才必须定义函数(参见3.2/2中的ODR).通常,如果从可能已评估的表达式调用非虚函数,则使用非虚函数.任何非纯虚函数都被认为是无条件使用的.当[非虚拟]特殊成员函数中使用的语言标准的专用位置被定义.等等.
在第一个示例中,您将析构函数声明为非纯虚函数.这直接意味着你的析构函数是用来在你的程序.反过来,这意味着需要定义该析构函数.您未能提供定义,因此编译器报告了错误.
在第三个示例中,析构函数是非虚拟的.由于您没有在程序中使用析构函数,因此无需定义并编译代码(有关使用析构函数的详细说明,请参阅12.4 ).
在你的第二个例子中,你正在处理一个实现的怪癖,由构造函数内联的事实触发.由于析构函数是非纯虚拟的,因此需要定义.但是,您的编译器无法检测到错误,这就是代码似乎成功编译的原因.您可以在实现的细节中挖掘出这种行为的原因,但从C++的角度来看,这个例子与第一个案例一样,完全出于同样的原因.