我正在使用Eclipse-CDT在Ubuntu x64上设置一个C ++项目。我基本上是在打招呼世界并链接到商业第三方图书馆。
我已经包含了链接到其库的头文件,但我仍然遇到链接器错误。除了明显的问题之外,这里是否存在一些可能的问题(例如我99%确定我正在链接到正确的库)。
Eclipse说:
Building target: LinkProblem Invoking: GCC C++ Linker g++ -L/home/notroot/workspace/somelib-3/somelib/target/bin -o"LinkProblem" ./src/LinkProblem.o -lsomelib1 -lpthread -lsomelib2 -lsomelib3 ./src/LinkProblem.o: In function `main': /home/notroot/workspace/LinkProblem/Debug/../src/LinkProblem.cpp:17: undefined reference to `SomeClass::close()' ./src/LinkProblem.o: In function `SomeOtherClass': /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `SomeClass::SomeClass()' /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `vtable for SomeOtherClass' /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:151: undefined reference to `SomeClass::~SomeClass()' ./src/LinkProblem.o: In function `~SomeOtherClass': /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `vtable for SomeOtherClass' /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()' /home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()' collect2: ld returned 1 exit status make: *** [LinkProblem] Error 1
答案 0 :(得分:168)
此链接器错误通常(根据我的经验)意味着您已使用声明覆盖子类中的虚函数,但尚未给出该方法的定义。例如:
class Base
{
virtual void f() = 0;
}
class Derived : public Base
{
void f();
}
但你还没有给出f的定义。使用该类时,会出现链接器错误。就像普通的链接器错误一样,这是因为编译器知道你在说什么,但链接器找不到定义。这只是一个非常难以理解的信息。
答案 1 :(得分:73)
假设这些方法位于其中一个库中,它看起来像是一个排序问题。
将库链接到可执行文件时,它们按照声明的顺序完成 此外,链接器将仅采用解析当前未完成的依赖项所需的方法/函数。如果后续库然后使用对象最初不需要的方法/函数,那么您将缺少依赖项。
工作原理:
示例:
对象需要:
Lib 1提供:
Lib 2提供
如果这样链接:
gcc -o plop plop.o -l1 -l2
然后链接器将无法解析读写符号。
但如果我像这样链接应用程序:
gcc -o plop plop.o -l2 -l1
然后它将正确链接。由于l2解析了BatchRead和BatchWrite依赖项,但还添加了两个新的(读写)。当我们接下来与l1链接时,所有四个依赖关系都会被解析。
答案 2 :(得分:52)
当您更改类时,Qt C ++将显示此错误,使其现在继承自QObject(即,现在它可以使用信号/插槽)。运行qmake -r将调用moc并修复此问题。
如果您通过某种版本控制与他人合作,则需要对.pro文件进行一些更改(即添加/删除空白行)。当其他人获得您的更改并运行make时,make将会看到.pro文件已更改并自动运行qmake。这将使您的队友免于重复您的挫败感。
答案 3 :(得分:15)
对我而言,这个问题非常模糊。我的班级看起来像这样:
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() { }
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
//-----------------------------------------
//-----------------------------------------
// main.h
class derived : public base {
public:
virtual int foo() ;
};
//-----------------------------------------
//-----------------------------------------
// main.cpp
int main () {
derived d;
}
//-----------------------------------------
问题出在链接器中。我的头文件在某个库中进入,但是所有的虚函数都在类声明中声明为'inline'。由于没有使用虚函数的代码(尚未),编译器或链接器忽略了将实际的函数体放在适当的位置。它也无法创建vtable。
在我从这个类派生的主代码中,链接器试图将我的类连接到基类和他的vtable。但vtable已被丢弃。
解决方案是在类声明之外声明至少一个虚函数体,如下所示:
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() ; //-- No longer declared 'inline'
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
base::~base()
{
}
//-----------------------------------------
答案 4 :(得分:9)
关于Qt4的问题,我无法使用上面提到的qmake moc选项。但无论如何这不是问题。我在类定义中有以下代码:
class ScreenWidget : public QGLWidget
{
Q_OBJECT // must include this if you use Qt signals/slots
...
};
我必须删除“Q_OBJECT”行,因为我没有定义信号或插槽。
答案 5 :(得分:8)
我收到此错误消息。问题是我在头文件中声明了一个虚拟析构函数,但实际上没有实现虚函数的主体。
答案 6 :(得分:5)
当我们简单地在基类中声明一个没有任何定义的虚函数时,也会发生这个错误。
例如:
class Base
{
virtual void method1(); // throws undefined reference error.
}
将上述声明更改为以下声明,它将正常工作。
class Base
{
virtual void method1()
{
}
}
答案 7 :(得分:4)
在我的情况下,当我忘记在我的纯虚拟类中的一个函数上添加= 0时出现问题。当添加= 0时,它被修复。和上面的弗兰克一样。
class ISettings
{
public:
virtual ~ISettings() {};
virtual void OKFunction() =0;
virtual void ProblemFunction(); // missing =0
};
class Settings : ISettings
{
virtual ~Settings() {};
void OKFunction();
void ProblemFunction();
};
void Settings::OKFunction()
{
//stuff
}
void Settings::ProblemFunction()
{
//stuff
}
答案 8 :(得分:1)
我现在偶然发现了这个问题。应用程序定义了一个纯虚拟接口类,并且通过共享库提供的用户定义类应该实现该接口。链接应用程序时,链接器抱怨共享库不会为基类提供vtable和type_info,也不能在其他任何地方找到它们。 原来我只是忘了让接口的方法之一纯虚拟(即在声明结尾处省略了“= 0”。非常基本的,如果你不能将链接器诊断连接到的话,仍然很容易被忽视和令人费解根本原因。
答案 9 :(得分:0)
尝试使用Qt之类的“hello world”时出现此错误消息。通过正确运行qt moc(元对象编译器)并正确编译包含这些moc生成的文件,问题就消失了。
答案 10 :(得分:0)
如果你有一个带有纯虚函数的基类,请确保你的基类构造函数和析构函数有体,否则链接器会失败。
答案 11 :(得分:0)
我把它放在未来的访客中:
如果您收到有关创建Exception
对象的错误,那么它的原因可能是缺少what()
虚函数的定义。