gpt4 book ai didi

c++ - 使用多个命名空间对 vtable 的 undefined reference

转载 作者:行者123 更新时间:2023-11-28 01:32:57 28 4
gpt4 key购买 nike

我已经有几天遇到这个奇怪的链接问题了。我有一个带有 2 个命名空间的 C++ 项目(在 Ubuntu 16.04 中)。每个命名空间在单独的目录中都有 .h 和 .cpp 文件,这些文件编译成库 .a 文件。最后,所有内容都链接到一个可执行文件中。

项目非常大(OpenBTS 的修改)所以为了让它更容易,这基本上是我正在尝试做的:

//*****directory A:

//file: A.h

namespace1 {

class A {

public:
void functionA();
};
}

//file: A.cpp

#include <B.h>
#include <vector.h>

using namespace1;
using namespace2;

void A::functionA (){
B testB1;
B testB2;
testB2 = testB1; //works
testB1.functionB2(); //defined in B.h, works
testB1.functionB(); //undefined reference to 'namespace2::B::functionB() const'
std::vector<B> testvector;
testvector.push_back(testB1); //undefined reference to 'namespace2::B'
}

//

//******directory B:

//file: B.h

#include "C.h"
//class C was part of the project before I started editing it and should not be the problem because other classes derived from it compile without problem.
namespace 2{
class B: public C{
int varB;
public:
B(){};
~B(){};

void functionB() const; //overrides virtual functionB in class C
int functionB2() { return varB;}
void functionB2() //overrides pure virtual functionB2 in class C
};
}

//file B.cpp

#include "B.h"
using namespace2

void B::functionB(){
//code...
}

//main.cpp
//this creates an instance of A

最后,目录 A 中的所有文件都编译为 .o 文件,然后在库 A.a 中链接在一起,目录 B 也是如此。另外 main.cpp 编译为 main.o

然后所有链接:g++ -g -O2 -Wall -pthread -rdynamic -o exename main.o ../B/.libs/B.a ../A/.libs/A.a -la53 -lzmq -pthread

这是我得到错误的地方:

对“namespace2::B”的 undefined reference 对“namespace2::B::functionB() const”的 undefined reference

我已经检查过 B 中是否覆盖了所有虚函数,这似乎没问题。此外,当我在 namespace2 中的其他代码中使用类 B 时,没有问题,一切都可以正常编译。调用 B.h 中定义的函数是有效的,所以链接器似乎无法访问 B.cpp 中定义的函数?

有什么建议吗?

最佳答案

使用命名空间时,您应该将类​​方法的实现包装到命名空间以及 .cpp 文件中。您的 a.cpp 应该类似于:

//file: A.cpp

#include <B.h>
#include <vector.h>

namespace namespace1 {

using namespace2; // means 'look in namespace2' to the compiler

void A::functionA (){
B testB1;
B testB2;
testB2 = testB1;
testB1.functionB2();
testB1.functionB();
std::vector<B> testvector;
testvector.push_back(testB1);
}

} // namespace1

你的 b.cpp 应该是这样的:

//file B.cpp

#include "B.h"
namespace namespace2 {

void B::functionB() const{
//code...
}

} // namespace2

请注意,类型 B 的对象的实例化是有效的,因为构造函数是在类声明中定义的。 B::function2() 也是如此。另一方面,A::functionA()B::functionB() 位于全局命名空间中,而不是它们应该位于 namespace1 和 namespace2 中。

子句 using namespace_name; 没有定义您的 cpp 文件中的范围。它只是通知编译器查看该 namespace 以解析它将在该翻译单元中找到的符号。

您在尝试填充 vector 时遇到的错误可能是由于您的类型缺少 functionB() 的实现,因为它位于错误的(全局)命名空间中。因此类型 B 是不完整的,不能用于实例化模板类。

编辑:作为下面评论的跟进,经过反复试验,结果证明在代码方面一切都很好,但是由于 lib A 和 B 之间的循环依赖关系导致链接失败,这在这个虚拟示例中并不清晰可见,并且由于其他依赖项需要正确的链接顺序才能工作。

因此,对库的链接顺序进行简单的更改是不可行的。我的建议是尽可能避免循环依赖,或者使用 ld 特定选项 --start-group--end-group 来解决此类问题。在 gnu man pages 了解更多信息与ld有关。你会在互联网上找到很多关于它们的用法的例子。

希望这可以帮助解决您的问题。

关于c++ - 使用多个命名空间对 vtable 的 undefined reference ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50782483/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com