链接错误:重复符号

use*_*793 3 c++ linker header-files duplicate-symbol c++17

我有下面列出的 4 个源文件:

//a.h

#pragma once

namespace proj {
class A {} a;
} // namespace proj
Run Code Online (Sandbox Code Playgroud)
//b.h

#pragma once

namespace proj {
int foo();
} // namespace proj
Run Code Online (Sandbox Code Playgroud)
// b.cpp

#include "proj/a.h"

namespace proj {
int foo() {
  A b = a;
  return 0;
}
} // namespace proj
Run Code Online (Sandbox Code Playgroud)
// c.cpp

#include "proj/a.h"
#include "proj/b.h"

using namespace proj;

int main() {
  A b = a;
  foo();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我尝试编译时,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
Run Code Online (Sandbox Code Playgroud)

我认为发生这种情况是因为 b.cpp 是独立于 c.cpp 编译的,因此预处理器在每个文件中单独包含标头 ah,并且当需要链接时,链接器会找到符号 a 的两个版本。

a如何声明可在整个程序中使用的类的一个实例(在本例中)并避免上述链接错误?

参考

gcc-7 (Homebrew GCC 7.2.0_1) 7.2.0在 Mac OS X 10.13.3 上使用 gcc-7 ( ) 和-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'],
)
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 5

由于它被标记为 C++17,因此您可以利用新的内联变量语言功能:

namespace proj {
    class A {};
    inline A a;
} // namespace proj
Run Code Online (Sandbox Code Playgroud)

inline变量现在的行为方式与函数相同inline:您的多个定义会a折叠为一个。