我有以下4个源文件:
//a.h
#pragma once
namespace proj {
class A {} a;
} // namespace proj
//b.h
#pragma once
namespace proj {
int foo();
} // namespace proj
// b.cpp
#include "proj/a.h"
namespace proj {
int foo() {
A b = a;
return 0;
}
} // namespace proj
// c.cpp
#include "proj/a.h"
#include "proj/b.h"
using namespace proj;
int main() {
A b = a;
foo();
return 0;
}
当我尝试编译c.cpp
时,出现以下链接错误:
duplicate symbol proj::a in:
buck-out/gen/proj/c#compile-c.cpp.ob5f76e97,default/c.cpp.o
buck-out/gen/proj/b#default,static/libb.a(b.cpp.o)
duplicate symbol ___odr_asan._ZN4proj1aE in:
buck-out/gen/proj/c#compile-c.cpp.ob5f76e97,default/c.cpp.o
buck-out/gen/proj/b#default,static/libb.a(b.cpp.o)
ld: 2 duplicate symbols for architecture x86_64
collect2: error: ld returned 1 exit status
Build failed: Command failed with exit code 1.
stderr: duplicate symbol proj::a in:
buck-out/gen/proj/c#compile-c.cpp.ob5f76e97,default/c.cpp.o
buck-out/gen/proj/b#default,static/libb.a(b.cpp.o)
duplicate symbol ___odr_asan._ZN4proj1aE in:
buck-out/gen/proj/c#compile-c.cpp.ob5f76e97,default/c.cpp.o
buck-out/gen/proj/b#default,static/libb.a(b.cpp.o)
ld: 2 duplicate symbols for architecture x86_64
collect2: error: ld returned 1 exit status
我认为这是因为b.cpp与c.cpp分别编译,预处理器在每个文件中单独包含头文件a.h,当链接时,链接器会找到两个版本的符号a。
如何声明一个类(在本例中是a),使其可以在整个程序中使用并避免上述链接错误?
参考资料
我正在使用gcc-7(
gcc-7(Homebrew GCC 7.2.0_1)7.2.0
)在Mac OS X 10.13.3上,使用-std=c++17
。构建系统
这应该与问题无关,但如果有人觉得有用,也可以包括在内。
我正在使用buck编译代码(尽管这应该与问题无关),BUCK文件如下:
cxx_library(
name='a',
exported_headers=['a.h'],
visibility=['PUBLIC'],
)
cxx_library(
name='b',
exported_headers=['b.h'],
srcs = ['b.cpp'],
deps = [':a'],
visibility=['PUBLIC'],
)
cxx_binary(
name='c',
srcs = ['c.cpp'],
deps = [':a', ':b'],
)
a.h
声明了一个变量class A {} a;
,因此每个包含a.h
的 cpp 文件都会重新声明proj::a
。你需要在只有一个 cpp 文件中声明它,并将其作为 extern 在a.h
中声明。 - Richard Crittena
当作“默认值”。为什么这样做? - StoryTeller - Unslander Monica