C++ 对全局变量使用extern的正确方法是什么?

C++ 对全局变量使用extern的正确方法是什么?,c++,extern,C++,Extern,文件a.cc int a = 0; 文件b.cc #include "a.cc" 文件main.cc #include "b.cc" extern int a; int main() { } g++ -c a.cc g++ -c b.cc g++ main.cc a.o b.o error: multiple definitions of a 我在这里做错了什么?您包含了一个.cc(或.cpp)文件,这是错误的。不要那样做。您需要一个标题,在其中放入extern inta: //

文件a.cc

int a = 0;
文件b.cc

#include "a.cc"
文件main.cc

#include "b.cc"
extern int a;

int main() {


}

g++ -c a.cc
g++ -c b.cc
g++ main.cc a.o b.o
error: multiple definitions of a

我在这里做错了什么?

您包含了一个
.cc
(或
.cpp
)文件,这是错误的。不要那样做。您需要一个标题,在其中放入
extern inta

// a.h
// include guards omitted
extern int a;

// a.cc
#include "a.h"

int a;

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

// main.cc
#include "a.h"

int main(){
  // use a
}

你所做的正是链接器所说的:你提供了“a”的多个定义。a.cc和b.cc都将变量“a”定义为具有外部链接的对象

不要那样做


不要包含源文件。有时您确实想这样做,但同样,有时您想使用编译器告诉您的
goto

——您最终在所有三个翻译单元中定义了
!您需要的是另一种方式:重复包含的声明应该是extern,并且必须只有一个定义。例如:

// header: stuff.h
extern int a;
void foo();



使用include时,想象一下将所有文件放在一个文件中。这基本上是编译器看到的,因为在编译器阶段之前,预处理器包含了所有内容

所以你的main.cc开始像这样

int a;
extern int a;
编译器认为这没问题,因为没有初始值设定项的extern只是一个声明,所以没有为它分配内存。然而,“inta”是一个定义,所以main.o包含为a分配内存的指令

链接后,链接器会注意到a.o和b.o已经定义了“a”。“a”是因为这是它最初定义的地方,“b”是因为b包括了有定义的“a”

要解决这个问题,只需去掉main.cc中的“b.cc”。事实上,完全去掉b.cc是因为它没有意义


如果您真的想这样做,请使用extern int a为“a”创建一个单独的标题a.h。然后main.cc和b.cc可以自由地包含a.h,而无需重新定义a。

一般来说,您不应该是
\include
ing
.cc
文件,只包含
.h
文件。@Mark:不应该发生这种情况,您是否拥有所有如图所示的文件?您是否正在编译
.h
文件?如果是,不要这样做,只编译
.cc
文件。所有三个文件都需要操作变量。最好的方法是什么?在需要的地方声明变量,最好包括一个声明它的文件。定义变量一次,并且只定义一次。不这样做就违反了标准。
// second TU: main.cpp
#include "stuff.h"

int a; // `a` is stored in this TU

int main() {
  a = 6;
  foo();
  //  now a == 7
}
int a;
extern int a;