我只是遇到了以下错误:

(.gnu.linkonce。[内容]):定义 引用[方法][对象] 文件:(.gnu.linkonce。[内容]): 对' typeinfo for '的未定义引用 (名称)的

为什么可能会得到这些“未定义的引用typeinfo”链接错误之一? 有人能解释一下幕后发生了什么吗?


当前回答

我刚才有很多这样的错误。我将一个只包含头文件的类拆分为一个头文件和一个cpp文件。但是,我没有更新我的构建系统,所以cpp文件没有被编译。除了在头文件中声明但未实现的函数的未定义引用之外,我得到了很多此类typeinfo错误。

解决方案是重新运行构建系统来编译和链接新的cpp文件。

其他回答

当声明的(非纯)虚函数缺少主体时,就会发生这种情况。在你的类定义中,如下所示:

virtual void foo();

应该定义(内联或链接源文件中):

virtual void foo() {}

或声明为纯虚拟的:

virtual void foo() = 0;

在基类(抽象基类)中声明虚析构函数,因为不能将析构函数声明为纯虚函数,所以要么必须在抽象类中定义它,就像virtual ~base(){}这样的虚拟定义,要么在任何派生类中定义。

如果你没有做到这一点,你将在链接时以一个“未定义的符号”结束。 因为VMT在根据派生类中的实现更新表时,为所有纯虚函数提供了一个带有匹配NULL的条目。但对于非纯虚函数,则需要在链接时定义,以便更新VMT表。

使用c++filt来要求符号。比如$c++filt _ZTIN10storageapi8BaseHostE 将输出类似"typeinfo for storageapi::BaseHost"的内容。

我刚才有很多这样的错误。我将一个只包含头文件的类拆分为一个头文件和一个cpp文件。但是,我没有更新我的构建系统,所以cpp文件没有被编译。除了在头文件中声明但未实现的函数的未定义引用之外,我得到了很多此类typeinfo错误。

解决方案是重新运行构建系统来编译和链接新的cpp文件。

与上面的RTTI、NO-RTTI讨论类似,如果使用dynamic_cast而未能包含包含类实现的目标代码,也会发生此问题。

我在Cygwin上构建代码时遇到了这个问题,然后将代码移植到Linux上。make文件、目录结构甚至gcc版本(4.8.2)在这两种情况下都是相同的,但是代码在Cygwin上可以正确链接和操作,但在Linux上却无法链接。Red Hat Cygwin显然已经对编译器/链接器进行了修改,以避免目标代码链接需求。

Linux链接器错误消息正确地将我引导到dynamic_cast行,但本论坛早期的消息让我寻找缺少的函数实现,而不是实际的问题:缺少目标代码。我的解决方法是在基类和派生类中替换一个虚拟类型函数,例如virtual int isSpecialType(),而不是使用dynamic_cast。这种技术避免了仅仅为了使dynamic_cast正常工作而链接对象实现代码的需求。

在我的例子中,我使用了带有头文件等文件的第三方库。我子类化了一个类,当我尝试实例化我的子类时,发生了这样的链接错误。

正如@sergiy所提到的,知道这可能是“rtti”的问题,我设法通过将构造函数实现放在单独的.cpp文件中并将“-fno-rtti”编译标志应用到文件中来解决它。它工作得很好。

由于我仍然不太清楚这个链接错误的内部,我不确定我的解决方案是否通用。然而,我认为在尝试@francois提到的适配器方式之前值得一试。当然,如果所有源代码都可用(不是在我的情况下),最好在可能的情况下使用'-frtti'重新编译。

还有一件事,如果你选择尝试我的解决方案,试着让单独的文件尽可能简单,不要使用c++的一些花哨的功能。特别注意boost相关的事情,因为它很大程度上依赖于rtti。