【发布时间】:2018-08-09 22:31:36
【问题描述】:
我有四个要编译的 C++ 文件。两个是.h,两个是.cpp。我创建了一个生成两个对象并使用 g++ 编译它们的生成文件。在链接器坚持定义两次的 .h 文件之一中定义了一个 int 。我究竟做错了什么? 这些是源文件:
“foo.cpp”
#include "foo.h"
#include "bar.h"
int main ()
{
X();
}
“foo.h”
#ifndef j
#define j
bool a;
#endif
“bar.cpp”
#include "bar.h"
int X()
{
b = 0;
return b;
}
"bar.h"
#ifndef k
#define k
int b;
int X();
#endif
“生成文件”
exec: foo.o bar.o
g++ -oexec foo.o bar.o
foo.o: foo.cpp foo.h
bar.o: bar.cpp bar.h
这是我得到的编译错误:
/usr/bin/ld: bar.o:(.bss+0x0): multiple definition of `b'; foo.o:(.bss+0x4): first defined here
collect2: error: ld returned 1 exit status
附:不,这不是任务的一部分。我为这篇文章做了一个简化的例子。
【问题讨论】:
-
您不应该在标题中定义变量。当您包含标题时,它会导致在多个翻译单元中定义变量。
-
就像错误所说的那样,您有多个
b的定义,一个在bar.h中,一个在bar.cpp中。您应该告诉编译器bar.h中提到的b在其他地方定义为extern int b; -
补充一下@drescherjm 所说的,如果您需要在头文件中声明一个变量(以便它可以在多个.cpp 文件中使用),请将其设为“extern”。这与将类(非内联)的数据成员设为静态非常相似。
-
每个包含 bar.h 的翻译单元(可能是 cpp 文件)都有自己的
int b;,而糟糕的链接器无法处理。包含保护#ifndef k将防止在该翻译单元中包含多个标题,但无法帮助处理多个翻译单元,这就是您在这里遇到的问题。 -
@alterigel 最重要的是,不仅仅是 .h 中有一个,.cpp 中有一个 - 将它放在 .h 中可能会导致这个问题正常的代码库,因为标头可能会包含在多个 .cpp 文件中(即使使用仅保护来自同一编译单元(.cpp 文件)的多个包含的包含保护)
标签: c++ linker multiple-definition-error