我整整陷在"undefined reference to vtable..."
中。
实际上,我已经看到许多与"undefined reference to vtable..."
相关的答案
例如:
undefined reference to vtable "Transaction"
https://gcc.gnu.org/faq.html#vtables
某些人的问题是忘记编写虚拟函数,其他人则忘记了将.cpp文件添加到构建目录中。但是我想我已经注意到了。
A_1
和A_2
编译为共享库libA
。 A_2
源自A_1
。A_1.h
#ifndef include_A_1_h
#define include_A_1_h
class A_1
{
public:
A_1() {}
virtual ~A_1() {} // not pure-virtual function has defined
virtual void print() = 0;
private:
};
#endif
A_2.h
#ifndef include_A_2_h
#define include_A_2_h
#include "A_1.h"
class A_2 : public A_1
{
public:
A_2() {}
~A_2() {}
virtual void print();
private:
};
#endif
A_2.cpp
#include "A_2.h"
void A_2::print()
{
// empty
}
B_1
和B_2
编译为共享库libB
。 B_1
和B_2
是独立的。B_1.h
#ifndef include_B_1_h
#define include_B_1_h
#include <iostream>
#include <string.h>
class B_1
{
public:
B_1(const std::string &path);
~B_1();
private:
};
#endif
B_1.cpp
#include "B_1.h"
B_1::B_1(const std::string &path)
{
}
B_1::~B_1()
{
}
B_2.h
#ifndef include_B_2_h
#define include_B_2_h
class B_2
{
public:
B_2() {}
~B_2() {}
void fun();
private:
};
#endif
B_2.cpp
#include "B_2.h"
#include "A_1.h"
#include "A_2.h"
void B_2::fun()
{
A_1 *ptr = new A_2;
}
main.cpp
中使用两个共享库。在这里,出了点问题。 main.cpp
#include "B_1.h"
int main()
{
B_1 b1("name");
}
我正在使用以下命令进行编译:
g++ A_2.cpp -fPIC -shared -o libA.so
g++ B_1.cpp B_2.cpp -fPIC -shared -o libB.so
g++ main.cpp -L . -lA -lB
编译器说:
./libB.so: undefined reference to `vtable for A_2'
您会看到许多空函数,因为我忽略了一些无关的代码。但是在这种情况下,它仍然有错误。
有人可以帮助我吗?谢谢。
答案 0 :(得分:10)
在编译库B时还提供共享库A。
g++ B_1.cpp B_2.cpp -L . -lA -fPIC -shared -o libB.so
简单地说(我不是该主题的专家),g ++在幕后使用的ld链接程序是报告未定义符号的链接程序。编译main时,libB中无法解析的符号无法通过提供libA来解析,因为main显式使用了的所有符号都是使用libB解析的。
默认情况下:
稍后,您可以做很多灵活的事情,其中包括库之间的循环依赖关系(这里libA也可以依赖libB)。
要在第二步失败,您需要使用-z defs
明确告诉链接器如果存在未定义的符号,则失败。
g++ B1.cpp B2.cpp -z defs -fPIC -shared -o libB.so
/tmp/cchjkdnAk.o:在函数
A_2::A_2()': B2.cpp:(.text._ZN3A_2C2Ev[_ZN3A_2C5Ev]+0x1b): undefined reference to
vtable中针对A_2'collect2:错误:ld返回1退出状态
如果main.cpp编写为:
,则您的编译指令将正常工作#include "A_2.h"
#include "B_1.h"
int main()
{
A_1 *ptr = new A_2;
B_1 b1("name");
}
libA将被加载来解析main中的符号,而这些符号将被用于libB的缺失符号。