将extern用于全局变量的正确方法是什么?

时间:2011-07-04 20:25:41

标签: 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

我在这里做错了什么?

4 个答案:

答案 0 :(得分:5)

您包含.cc(或.cpp)个文件,这是错误的。不要那样做。你需要一个标题,并在其中放置extern int a;

// 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
}

答案 1 :(得分:1)

您正在完成链接器所说的内容:您提供了“a”的多个定义。 a.cc和b.cc都将变量'a'定义为具有外部链接的东西。

不要那样做!

不要#include源文件。有时您确实希望这样做,但有时您又想使用goto

答案 2 :(得分:0)

正是编译器告诉你的内容 - 你最终在所有三个翻译单元中定义 a!你反过来想要它:重复包含的声明应该是extern,并且必须只有一个定义。例如:

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


// first TU: a.cpp
#include "stuff.h"

void foo() { a += 1; }


// second TU: main.cpp
#include "stuff.h"

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

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

答案 3 :(得分:0)

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

所以你的main.cc开始看起来像这样。

int a;
extern int a;

编译器认为这没关系,因为没有初始化程序的extern只是一个声明,因此没有为它分配内存。 “int a”是一个定义,但是,main.o包含为a。

分配内存的指令

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

要解决此问题,请在main.cc中取出#include“b.cc”。事实上,完全取出b.cc是因为它没有意义。

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