我只是遇到了以下错误:

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

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


当前回答

处理RTTI和非RTTI库的代码的可能解决方案:

a)使用-frtti或-fno-rtti重新编译所有内容 b)如果a)对你来说不可能,试试下面的方法:

假设libfoo是在没有RTTI的情况下构建的。您的代码使用libfoo并使用RTTI编译。如果你在libfoo中使用一个有虚拟对象的类(Foo),你很可能会遇到一个链接时错误:Foo类缺少typeinfo。

定义另一个类(例如FooAdapter),它没有虚值,并且会将调用转发给你使用的Foo。

在一个不使用RTTI且仅依赖于libfoo符号的小型静态库中编译FooAdapter。为它提供一个头文件,并在代码中使用它(使用RTTI)。因为FooAdapter没有虚函数,它不会有任何类型信息,你将能够链接你的二进制文件。如果您使用许多来自libfoo的不同类,这个解决方案可能不方便,但这是一个开始。

其他回答

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

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

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

在我的情况下,这纯粹是一个库依赖问题,即使我有dynamic_cast调用。在makefile中添加了足够的依赖后,这个问题就消失了。

处理RTTI和非RTTI库的代码的可能解决方案:

a)使用-frtti或-fno-rtti重新编译所有内容 b)如果a)对你来说不可能,试试下面的方法:

假设libfoo是在没有RTTI的情况下构建的。您的代码使用libfoo并使用RTTI编译。如果你在libfoo中使用一个有虚拟对象的类(Foo),你很可能会遇到一个链接时错误:Foo类缺少typeinfo。

定义另一个类(例如FooAdapter),它没有虚值,并且会将调用转发给你使用的Foo。

在一个不使用RTTI且仅依赖于libfoo符号的小型静态库中编译FooAdapter。为它提供一个头文件,并在代码中使用它(使用RTTI)。因为FooAdapter没有虚函数,它不会有任何类型信息,你将能够链接你的二进制文件。如果您使用许多来自libfoo的不同类,这个解决方案可能不方便,但这是一个开始。

一个可能的原因是声明了虚函数而没有定义它。

当你声明它而没有在同一个编译单元中定义它时,你就表明它在其他地方定义了——这意味着链接器阶段将尝试在其他编译单元(或库)中找到它。

定义虚函数的一个例子是:

virtual void fn() { /* insert code here */ }

在本例中,您将定义附加到声明中,这意味着链接器稍后不需要解析它。

这条线

virtual void fn();

声明fn()而不定义它,这将导致您所要求的错误消息。

它与代码非常相似:

extern int i;
int *pi = &i;

它声明整数I在另一个编译单元中声明,必须在链接时解析(否则PI不能设置为它的地址)。

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

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