我只是遇到了以下错误:
(.gnu.linkonce。[内容]):定义 引用[方法][对象] 文件:(.gnu.linkonce。[内容]): 对' typeinfo for '的未定义引用 (名称)的
为什么可能会得到这些“未定义的引用typeinfo”链接错误之一? 有人能解释一下幕后发生了什么吗?
我只是遇到了以下错误:
(.gnu.linkonce。[内容]):定义 引用[方法][对象] 文件:(.gnu.linkonce。[内容]): 对' typeinfo for '的未定义引用 (名称)的
为什么可能会得到这些“未定义的引用typeinfo”链接错误之一? 有人能解释一下幕后发生了什么吗?
当前回答
引用gcc手册:
对于多态类(具有虚函数的类),type_info对象与虚表[…对于所有其他类型,我们在使用type_info对象时写出type_info对象:当将' typeid'应用到表达式、抛出对象或在catch子句或异常规范中引用类型时。
在同一页稍早的地方
如果类声明了任何非内联、非纯虚函数,则选择第一个虚函数作为类的“key方法”,虚表只在定义key方法的转换单元中发出。
因此,当“key方法”缺少它的定义时,就会发生这个错误,正如前面提到的其他答案。
其他回答
当声明的(非纯)虚函数缺少主体时,就会发生这种情况。在你的类定义中,如下所示:
virtual void foo();
应该定义(内联或链接源文件中):
virtual void foo() {}
或声明为纯虚拟的:
virtual void foo() = 0;
一个可能的原因是声明了虚函数而没有定义它。
当你声明它而没有在同一个编译单元中定义它时,你就表明它在其他地方定义了——这意味着链接器阶段将尝试在其他编译单元(或库)中找到它。
定义虚函数的一个例子是:
virtual void fn() { /* insert code here */ }
在本例中,您将定义附加到声明中,这意味着链接器稍后不需要解析它。
这条线
virtual void fn();
声明fn()而不定义它,这将导致您所要求的错误消息。
它与代码非常相似:
extern int i;
int *pi = &i;
它声明整数I在另一个编译单元中声明,必须在链接时解析(否则PI不能设置为它的地址)。
我在这个错误上花了几个小时,虽然这里的其他答案帮助我理解发生了什么,但它们并没有解决我的特定问题。
我正在开发一个使用clang++和g++进行编译的项目。我没有使用clang++的链接问题,但得到了未定义的引用'typeinfo错误与g++。
重点是:在g++中,连接顺序很重要。如果你以不正确的顺序列出你想要链接的库,你会得到typeinfo错误。
有关与gcc/g++链接顺序的更多细节,请参阅这个SO问题。
在我的情况下,这纯粹是一个库依赖问题,即使我有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的不同类,这个解决方案可能不方便,但这是一个开始。