我只是遇到了以下错误:

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

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


当前回答

前面的答案是正确的,但是这个错误也可能是由于试图对没有虚函数的类的对象使用typeid而导致的。c++ RTTI需要虚表,因此希望对其执行类型标识的类至少需要一个虚函数。

如果希望类型信息作用于一个实际上不需要任何虚函数的类,可以将析构函数设为虚函数。

其他回答

如果你要将一个。so链接到另一个。so,还有一种可能性是在gcc或g++中使用"-fvisibility=hidden"进行编译。如果两个.so文件都是用"-fvisibility=hidden"构建的,并且key方法不相同。so作为另一个虚函数的实现,后者将看不到前者的虚表或typeinfo。对于链接器来说,这看起来像一个未实现的虚函数(就像paxdiablo和cdleary的答案一样)。

在这种情况下,必须为基类的可见性做出例外

__attribute__ ((visibility("default")))

在类声明中。例如,

class __attribute__ ((visibility("default"))) boom{
    virtual void stick();
}

当然,另一个解决方案是不使用"-fvisibility=hidden "。这使得编译器和链接器的事情变得复杂,可能会损害代码的性能。

我有同样的错误时,我的接口(与所有纯虚函数)需要一个更多的函数,我忘记“空”它。

我有

class ICommProvider { public: /** * @brief If connection is established, it sends the message into the server. * @param[in] msg - message to be send * @return 0 if success, error otherwise */ virtual int vaSend(const std::string &msg) = 0; /** * @brief If connection is established, it is waiting will server response back. * @param[out] msg is the message received from server * @return 0 if success, error otherwise */ virtual int vaReceive(std::string &msg) = 0; virtual int vaSendRaw(const char *buff, int bufflen) = 0; virtual int vaReceiveRaw(char *buff, int bufflen) = 0; /** * @bief Closes current connection (if needed) after serving * @return 0 if success, error otherwise */ virtual int vaClose(); };

Last vaClose不是虚拟的,所以编译时不知道从哪里获得它的实现,因此感到困惑。我传达的信息是:

…TCPClient.o:(.rodata+0x38): undefined reference to ' typeinfo for ICommProvider'

简单的更改

virtual int vaClose();

to

virtual int vaClose() = 0;

修复了问题。希望能有所帮助

前面的答案是正确的,但是这个错误也可能是由于试图对没有虚函数的类的对象使用typeid而导致的。c++ RTTI需要虚表,因此希望对其执行类型标识的类至少需要一个虚函数。

如果希望类型信息作用于一个实际上不需要任何虚函数的类,可以将析构函数设为虚函数。

我在这个错误上花了几个小时,虽然这里的其他答案帮助我理解发生了什么,但它们并没有解决我的特定问题。

我正在开发一个使用clang++和g++进行编译的项目。我没有使用clang++的链接问题,但得到了未定义的引用'typeinfo错误与g++。

重点是:在g++中,连接顺序很重要。如果你以不正确的顺序列出你想要链接的库,你会得到typeinfo错误。

有关与gcc/g++链接顺序的更多细节,请参阅这个SO问题。

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

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

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

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

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

这条线

virtual void fn();

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

它与代码非常相似:

extern int i;
int *pi = &i;

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