一、变量的声明和定义
C++的分离编译机制允许程序拆分成多个文件来写,最常见的是在头文件中进行声明,源文件中进行定义,然后一起编译:
1 |
gcc a.h a.cpp -o a.o |
声明使得函数或者变量被程序所知,定义负责创建与声明相关联的实体。变量只能被定义一次,但能多次声明。
声明变量的两种方式:
- 使用 extern 关键字且没有被显示初始化,如
extern int i;
- 不使用 extern 关键字且没有被显示初始化,如
int i;
一旦一个变量被显示初始化了,该条语句就会被认为是定义,例如 extern double pi = 3.14;
。
二、声明和定义的必要性
声明和定义在多个文件中比较重要,特别是对于在多个文件中都要使用的同一个变量,必须进行声明。
例如三个文件 test.h
, test1.cpp
和 test2.cpp
中都要使用同一个全局变量的情况:
1 2 3 4 |
// test.h extern int gCnt; // 对全局变量 gCnt 进行声明 int f1(); // 声明函数 f1(),可以不加 extern int f2(); // 声明函数 f2() |
1 2 3 4 5 |
// test1.cpp int gCnt; // 定义 gCnt int f1(){ return gCnt; } |
1 2 3 4 5 6 |
// test2.cpp #include"test.h" // 无需再对 gCnt 进行定义 int f2(){ return gCnt } |
main.cpp
1 2 3 4 5 6 7 8 9 |
#include<iostream> #include"testa.h" using namespace std; int main() { cout << f1() << endl; cout << f2() << endl; return 0; } |
编译运行,程序输出:
1 2 |
0 0 |
test.h
中声明变量 gCnt
,另外的两个文件中分别引用头文件,并且其中一个定义 gCnt
。由于变量只能被定义一次,所以不能同时在 test1.cpp
和 test2.cpp
中定义 gCnt
,否则会报错:
1 2 3 |
/tmp/cc2lxN5u.o:(.bss+0x0): multiple definition of `gCnt' /tmp/ccWKRQpn.o:(.data+0x0): first defined here collect2: error: ld returned 1 exit status |
根据变量的默认初始化规则,test1.cpp
中的全局变量 gCnt
会被默认初始化为 0
,就相当于执行了 int gCnt=1;
。
值得注意的是,头文件中的 extern
关键字不能省,因为省略 extern
编译器会把它当作全局变量定义。然后被同时两个 cpp 文件包含,预处理阶段就会生成两个 gCnt
的定义,导致编译错误:
1 2 3 4 5 |
/tmp/cc1Y7L4l.o:(.bss+0x0): multiple definition of `gCnt' /tmp/ccsAd6YS.o:(.bss+0x0): first defined here /tmp/cc99tPeP.o:(.bss+0x0): multiple definition of `gCnt' /tmp/ccsAd6YS.o:(.bss+0x0): first defined here collect2: error: ld returned 1 exit status |
评论