GCC C++链接器错误:未定义引用'vtable for XXX',未定义引用'ClassName :: ClassName()'

Ale*_*ack 70 c++ linker g++ eclipse-cdt

我正在使用Eclipse-CDT在Ubuntu x64上设置一个C++项目.我基本上是在打招呼世界并链接到商业第三方图书馆.

我已经包含了链接到其库的头文件,但我仍然遇到链接器错误.除了明显的问题之外,这里是否存在一些可能的问题(例如我99%肯定我正在链接到正确的库).

  1. 有没有办法确认我链接的静态库是64位?
  2. 有没有办法确认该库是否具有我期望它具有的类(和方法)?

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

mgi*_*uca 166

这通常链接错误(在我的经验),意味着你已经覆盖在声明子类中的虚函数,但没有给出该方法的定义.例如:

class Base
{
    virtual void f() = 0;
}
class Derived : public Base
{
    void f();
}
Run Code Online (Sandbox Code Playgroud)

但是你还没有给出f的定义.使用该类时,会出现链接器错误.就像普通的链接器错误一样,这是因为编译器知道你在说什么,但链接器找不到定义.这只是一个非常难以理解的消息.

  • 谢谢.我找不到2个小时的解决方案. (3认同)
  • 非常感谢!这也解决了我的问题. (2认同)
  • 正是我遇到的问题.谢谢你节省了我的时间和精力. (2认同)

Mar*_*ork 74

假设这些方法位于其中一个库中,它看起来像一个排序问题.

将库链接到可执行文件时,它们按照声明的顺序完成.
此外,链接器将仅采用解析当前未完成的依赖项所需的方法/函数.如果后续库然后使用对象最初不需要的方法/函数,那么您将缺少依赖项.

这个怎么运作:

  • 获取所有目标文件并将它们组合成可执行文件
  • 解决目标文件之间的任何依赖关系.
  • 按顺序为每个库:
    • 检查未解析的依赖项,并查看lib是否解析它们.
    • 如果需要加载部分到可执行文件中.

例:

对象需要:

  • 打开
  • BatchRead
  • BatchWrite

Lib 1提供:

  • 打开

Lib 2提供

  • BatchRead(但使用lib1:read)
  • BatchWrite(但使用lib1:write)

如果像这样链接:

gcc -o plop plop.o -l1 -l2

然后链接器将无法解析读写符号.

但如果我像这样链接应用程序:

gcc -o plop plop.o -l2 -l1

然后它将正确链接.由于l2解析了BatchRead和BatchWrite依赖项,但还添加了两个新的(读取和写入).当我们接下来与l1链接时,所有四个依赖关系都被解析.

  • 这对我真的很有帮助!我的groupproject突然停止从我的一个libs接受新的cpp文件,它是关于未定义的引用,然后我切换位置,它作为一个魅力.说真的,在这个问题的某些页面上应该有一篇更具体的文章.非常感谢马丁! (3认同)
  • 没有用你正在使用的东西.如果你的代码包含C++东西,你需要使用g ++来获得正确的标准库. (2认同)

Ric*_*ith 52

更改类时,Qt C++将显示此错误,使其现在继承自QObject(即,现在它可以使用信号/插槽).运行qmake -r将调用moc并修复此问题.

如果您通过某种版本控制与其他人合作,则需要对.pro文件进行一些更改(即添加/删除空白行).当其他人获得您的更改并运行make时,make将会看到.pro文件已更改并自动运行qmake.这将使您的队友免于重复您的挫败感.

  • +1000 - 这*完全*解决了我的问题. (11认同)
  • 这是我的问题.谢谢! (4认同)

pho*_*ord 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;
}
//-----------------------------------------
Run Code Online (Sandbox Code Playgroud)

问题出在链接器中.我的头文件在某个库中进入,但是所有的虚函数都在类声明中声明为'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() 
{
}
//-----------------------------------------
Run Code Online (Sandbox Code Playgroud)


小智 9

关于Qt4的问题,我无法使用上面提到的qmake moc选项.但无论如何这不是问题.我在类定义中有以下代码:

class ScreenWidget : public QGLWidget
{
   Q_OBJECT        // must include this if you use Qt signals/slots
...
};
Run Code Online (Sandbox Code Playgroud)

我不得不删除"Q_OBJECT"行,因为我没有定义信号或插槽.


luk*_*ina 8

我有这个错误消息.问题是我在头文件中声明了一个虚拟析构函数,但实际上没有实现虚函数的主体.


小智 5

当我们简单地在基类中声明没有任何定义的虚函数时,也会发生此错误.

例如:

class Base
{
    virtual void method1(); // throws undefined reference error.

}
Run Code Online (Sandbox Code Playgroud)

将上述声明更改为以下声明,它将正常工作.

class Base
{
    virtual void method1()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)