GCC C++ 链接器错误:未定义对 'vtable for XXX' 的引用,对 'ClassName::ClassName()' 的未定义引用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1095298/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()'
提问by Alex Black
I'm setting up a C++ project, on Ubuntu x64, using Eclipse-CDT. I'm basically doing a hello world and linking to a commerical 3rd party library.
我正在使用 Eclipse-CDT 在 Ubuntu x64 上设置 C++ 项目。我基本上是在做一个 hello world 并链接到一个商业 3rd 方库。
I've included the header files, linked to their libraries, but I still get linker errors. Are there some possible problems here other than the obvious (e.g. I am 99% sure I'm linking to the correct library).
我已经包含了头文件,链接到他们的库,但我仍然收到链接器错误。除了显而易见的问题之外,这里是否还有一些可能的问题(例如,我 99% 确定我正在链接到正确的库)。
- Is there a way to confirm the static libraries I am linking to are 64bit?
- Is there a way to confirm that the library has the class (and methods) I am expecting it to have?
- 有没有办法确认我链接到的静态库是 64 位的?
- 有没有办法确认图书馆拥有我期望的类(和方法)?
Eclipse says:
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
回答by mgiuca
This linker error usually (in my experience) means that you've overridden a virtual function in a child class with a declaration, but haven't given a definition for the method. For example:
这个链接器错误通常(根据我的经验)意味着您已经使用声明覆盖了子类中的虚函数,但没有给出该方法的定义。例如:
class Base
{
virtual void f() = 0;
}
class Derived : public Base
{
void f();
}
But you haven't given the definition of f. When you use the class, you get the linker error. Much like a normal linker error, it's because the compiler knew what you were talking about, but the linker couldn't find the definition. It's just got a very difficult to understand message.
但是你还没有给出 f 的定义。当您使用该类时,您会收到链接器错误。很像一个普通的链接器错误,这是因为编译器知道你在说什么,但链接器找不到定义。它只是有一个非常难以理解的消息。
回答by Martin York
Assuming those methods are in one of the libs it looks like an ordering problem.
假设这些方法在其中一个库中,它看起来像是一个排序问题。
When linking libraries into an executable they are done in the order they are declared.
Also the linker will only take the methods/functions required to resolve currently outstanding dependencies. If a subsequent library then uses methods/functions that were not originally required by the objects you will have missing dependencies.
将库链接到可执行文件时,它们是按照声明的顺序完成的。
此外,链接器将只采用解决当前未解决的依赖项所需的方法/函数。如果随后的库使用对象最初不需要的方法/函数,您将缺少依赖项。
How it works:
这个怎么运作:
- Take all the object files and combine them into an executable
- Resolve any dependencies among object files.
- For-each library in order:
- Check unresolved dependencies and see if the lib resolves them.
- If so load required part into the executable.
- 获取所有目标文件并将它们组合成一个可执行文件
- 解决目标文件之间的任何依赖关系。
- 按顺序为每个库:
- 检查未解决的依赖项,看看 lib 是否解决了它们。
- 如果是这样,将所需的部分加载到可执行文件中。
Example:
例子:
Objects requires:
对象要求:
- Open
- Close
- BatchRead
- BatchWrite
- 打开
- 关闭
- 批量读取
- 批量写入
Lib 1 provides:
Lib 1 提供:
- Open
- Close
- read
- write
- 打开
- 关闭
- 读
- 写
Lib 2 provides
Lib 2 提供
- BatchRead (but uses lib1:read)
- BatchWrite (but uses lib1:write)
- BatchRead(但使用 lib1:read)
- BatchWrite(但使用 lib1:write)
If linked like this:
如果这样链接:
gcc -o plop plop.o -l1 -l2
gcc -o plop plop.o -l1 -l2
Then the linker will fail to resolve the read and write symbols.
然后链接器将无法解析读写符号。
But if I link the application like this:
但是,如果我像这样链接应用程序:
gcc -o plop plop.o -l2 -l1
gcc -o plop plop.o -l2 -l1
Then it will link correctly. As l2 resolves the BatchRead and BatchWrite dependencies but also adds two new ones (read and write). When we link with l1 next all four dependencies are resolved.
然后它将正确链接。由于 l2 解决了 BatchRead 和 BatchWrite 依赖项,但还添加了两个新的依赖项(读取和写入)。当我们与 l1 链接时,所有四个依赖项都解决了。
回答by Rick Smith
Qt C++ will show this error when you change a class such that it now inherits from QObject (ie so that it can now use signals/slots). Running qmake -r will call moc and fix this problem.
当您更改一个类时,Qt C++ 将显示此错误,使其现在从 QObject 继承(即它现在可以使用信号/插槽)。运行 qmake -r 将调用 moc 并解决此问题。
If you are working with others via some sort of version control, you will want to make some change to your .pro file (ie add/remove a blank line). When everyone else gets your changes and runs make, make will see that the .pro file has changed and automatically run qmake. This will save your teammates from repeating your frustration.
如果您通过某种版本控制与其他人合作,您将需要对您的 .pro 文件进行一些更改(即添加/删除一个空行)。当其他人得到您的更改并运行 make 时,make 将看到 .pro 文件已更改并自动运行 qmake。这将使您的队友免于重复您的挫败感。
回答by phord
The problem for me turned out to be pretty obscure. My class looked like this:
对我来说,这个问题非常模糊。我的课是这样的:
//-----------------------------------------
// 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;
}
//-----------------------------------------
The problem is in the linker. My header file went in a library somewhere, but all the virtual functions were declared 'inline' in the class declaration. Since there was no code using the virtual functions (yet), the compiler or linker neglected to put actual function bodies in place. It also failed to create the vtable.
问题出在链接器上。我的头文件放在某个库中,但所有虚函数都在类声明中被声明为“内联”。由于没有代码使用虚函数(还),编译器或链接器忽略了将实际函数体放置到位。它也未能创建 vtable。
In my main code where I derived from this class, the linker tried to connect my class to the base class and his vtable. But the vtable had been discarded.
在我从这个类派生的主要代码中,链接器试图将我的类连接到基类和他的 vtable。但是vtable已经被丢弃了。
The solution was to declare at least one of the virtual functions' bodies outside the class declaration, like this:
解决方案是在类声明之外至少声明一个虚函数体,如下所示:
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() ; //-- No longer declared 'inline'
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
base::~base()
{
}
//-----------------------------------------
回答by mschachter
In regards to problems with Qt4, I couldn't use the qmake moc option mentioned above. But that wasn't the problem anyway. I had the following code in the class definition:
关于Qt4的问题,我无法使用上面提到的qmake moc选项。但无论如何这都不是问题。我在类定义中有以下代码:
class ScreenWidget : public QGLWidget
{
Q_OBJECT // must include this if you use Qt signals/slots
...
};
I had to remove the line "Q_OBJECT" because I had no signals or slots defined.
我不得不删除“Q_OBJECT”行,因为我没有定义信号或槽。
回答by lukeinchina
I had this error message. The problem was that I declared a virtual destructor in the header file, but the virtual functions' body was actually not implemented.
我有这个错误信息。问题是我在头文件中声明了一个虚析构函数,但是虚函数体实际上并没有实现。
回答by user2376546
This error will also occur when we simply declare a virtual function without any definition in the base class.
当我们简单地声明一个虚函数而在基类中没有任何定义时,也会出现这个错误。
For example:
例如:
class Base
{
virtual void method1(); // throws undefined reference error.
}
Change the above declaration to the below one, it will work fine.
将上面的声明更改为下面的声明,它会正常工作。
class Base
{
virtual void method1()
{
}
}
回答by Lars Persson
In my case the problem occured when i forgot to add the =0 on one function in my pure virtual class. It was fixed when the =0 was added. The same as for Frank above.
在我的情况下,当我忘记在纯虚拟类中的一个函数上添加 =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
}
回答by frank
I stumbled across the issue now, too. The application defined a pure virtual interface class and a user-defined class provided through a shared lib was supposed to implement the interface. When linking the application, the linker complained that the shared lib would not provide vtable and type_info for the base class, nor could they be found anywhere else. Turned out that I simply forgot to make one of the interface's methods pure virtual (i.e. omitted the " = 0" at the end of the declaration. Very rudimentary, still easy to overlook and puzzling if you can't connect the linker diagnostic to the root cause.
我现在也偶然发现了这个问题。应用程序定义了一个纯虚拟接口类和一个通过共享库提供的用户定义类来实现该接口。链接应用程序时,链接器抱怨共享库不会为基类提供 vtable 和 type_info,也无法在其他任何地方找到它们。原来我只是忘记将接口的方法之一设为纯虚拟的(即省略声明末尾的“= 0”。非常初级,如果您无法将链接器诊断连接到根本原因。
回答by awallin
I had this error message when trying "hello world" like things with Qt. The problems went away by correctly running the qt moc (meta object compiler) and compiling+including these moc-generated files correctly.
在尝试使用 Qt 之类的“hello world”时,我收到了此错误消息。通过正确运行qt moc(元对象编译器)并正确编译+包含这些moc生成的文件,问题就消失了。