2013-12-23 66 views
0

我正在写一个小的学生项目,并且遇到了一些问题,我有几个全局变量,需要在几个源文件中使用它,但是我得到错误* undefined引用了variable_name *。让我们创建三个源文件,例如:C++如何正确初始化全局变量?

tst1.h:

extern int global_a; 
void Init(); 

tst1.cpp:

#include "tst1.h" 
void Init(){ 
    global_a = 1; 
} 

tst2.cpp:

#include "tst1.h" 
int main(){ 
    Init(); 
} 

当我编译和链接,这就是我得到的:

$ g++ -c tst1.cpp 
$ g++ -c tst2.cpp 
$ g++ tst2.o tst1.o 
tst1.o: In function `Init()': 
tst1.cpp:(.text+0x6): undefined reference to `global_a' 
collect2: error: ld returned 1 exit status 

如果我删除EXTERN声明,然后我得到了另外一个问题,让我显示:

$ g++ -c tst1.cpp 
$ g++ -c tst2.cpp 
$ g++ tst2.o tst1.o 
tst1.o:(.bss+0x0): multiple definition of `global_a' 
tst2.o:(.bss+0x0): first defined here 
collect2: error: ld returned 1 exit status 

但我真的需要一些变量是全球性的,例如我的小项目与汇编代码,并有一个变量,如string rax =“%rax%eax%ax%ah%al”;应该通过不同的源文件引用它。

那么,如何正确初始化全局变量呢?

+2

对此的最佳解决方案是不使用全局变量。有关如何避免它们的提示:依赖注入。 –

+0

@Tim,我知道,全局变量是不好的风格,但在某些情况下,它是正确的方式。例如,如果我的项目和汇编一起工作,那么许多文件应该知道CPU寄存器的名称,并且应该通过不同的源文件引用变量'string rax ='%rax%eax%ax%ah%al';'。 –

+0

一般来说,静态类成员应该是首选。 – leemes

回答

3

您只声明变量但未定义它。此记录

extern int global_a; 

是一个声明不是定义。给任何一个模块中定义它,你能写

int global_a; 

或者它会更好地定义函数初始化以下方式

int Init { /* some code */; return 1; } 

,并在主要模块功能之前主要写

int global_a = Init(); 
+0

正如我在下面评论的,编译器说'tst1.cpp:2:5:错误:重新定义'int global_a'。 –

+0

对不起,我还没有理解你评论的内容。我展示了一个相关的代码。你无法简单地复制和粘贴它? –

+0

我只是写在全局范围'int global_a;'的tst1.cpp中。编译器给出错误。 –

2

tst1.cpp应阅读代替:

#include "tst1.h" 

int global_a = 1; 

void Init(){ 
} 

你也可以写初始化路线为:

int global_a(1); 

还是在C++ 11:

int global_a{1}; 

一个全球唯一的应被定义为(即没有写入extern前缀)在一个源文件和而不是在头文件中。

+0

不,这就是我得到的: 'tst1.cpp:2:5:错误:重新定义'int global_a' int global_a = 33; ^ 从tst1.cpp包含的文件中:1:0: tst1.h:1:5:错误:先前在此处声明的'int global_a' int global_a; ^' –

+0

对不起,格式化。不久它说'tst1.cpp:2:5:错误:重新定义'int global_a'' –

+0

我假设你的'tst1.h'具有'extern int global_a;',**正如你在问题中所写的那样**不只是'int global_a;'。 –

0

您需要添加

#ifndef TST1_H 
#define TST1_H 
..... 
#endif 

to tst1.h.它在tst2中包含两次。cpp

+1

不,它不包含两次,它被编译了两次(以不同的翻译单位)。包括警卫并没有解决这个问题。 – leemes