我们在编译模块中的任意一个文件中书写的变量/函数在此模块中其他文件中都可以被访问到,但是其他编译模块的文件是没有访问此变量的权限的。那么如何跨模块共享变量 / 函数呢?
答案就是使用 extern
. 在这里请在做的各位牢牢记住它的定义:标示所修饰的变量或函数的可能位于其他模块。
一定要牢牢记住上面的定义, 带着定义我们就可以想明白以下问题:
implementation file
中使用一个外部变量要先 extern
声明该变量 (或者导入该变量所在的 header file
)?header file
中要使用 extern 声明一个变量?这样当我们编译某个单元时, 编译器发现了使用 extern
修饰的变量,
ld: symbol(s) not found for architecture x86_64
;test1.h
中声明 extern int a;
test1.cpp
中定义 int a = 10;
(或者使用 int a;
定义, 这样的话值是默认值 0)test2.cpp
中 #include "test1.h"
, 这样便可以在 test2.cpp
中直接使用 a 变量了.在头文件 test1.h
中直接 extern int a = 10;
这样属于在头文件中直接定义, 我们已经说了 一个变量可以被多处声明, 但只能定义在一处
, 在这种情况下如果有多个 implementation file
都 #include "test1.h"
, 那么会造成在 obj
文件的 链接
阶段发现多处存在同一个变量的定义, 这时会报错 ld: 1 duplicate symbol for architecture x86_64
在头文件中定义一个变量属于非常业余的做法, 请不要争相模仿
在头文件 test1.h
中 直接 extern int a = 10;
在 test2.cpp
中直接使用 extern int a;
(没有 #include test1.h
)
这样做可以避免多处重复定义的问题, 但是这样的话 test1.h
定义的其他变量与方法都不可以使用了, 必须全部使用 extern ***
的形式进行声明然后使用, 这样会及其得不偿失.
所以我们可以得出结论:只在头文件中做声明!!!
真理总是这么简单!
函数与变量类似, 也分为定义与声明. 但是与变量在声明时必须要包含 extern
不同, 由于函数的定义和声明是有区别的:
所以函数定义和声明时都可以将 extern
省略掉, 反正其他文件也是知道这个函数是在其他地方定义的, 所以不加 extern
也行.
所以在 cpp 中, 如果在一个函数前添加了 extern, 那么仅表示此函数可能在别的模块中定义; 或者也可以让我们在只使用了某个头文件的这个方法时不用
#include <***.h>
static
使用当 static
用于修饰类中的变量/函数,表明该变量/函数是一个静态成员变量/函数:
当 static
用于修饰类之外的变量/函数,表明该变量/函数是一个普通的全局静态成员变量/函数:
extern
声明也不可以), 不是真正意义的全局(普通的函数默认是 extern
的)static
, 比如函数中要返回一个数组, 不想让这个数组函数结束时被释放, 那么可以使用 static 修饰此局部变量static
使变量只在本编译模块内部可见, 这样的话如果两个编译模块各自都有一个 value
变量的话, 那么千万不要将两个编译模块内 static 修饰的变量认为是同一份内存, 他们实际上是两份内存, 修改其中一个不会影响另外一个
当 const
单独使用时它就与 static
相同, 而当与 extern
一起合作的时候, 它的特性就跟 extern
的一样了。
#ifndef
能保证你的头文件在本编译模块只被编译一次(但是多个模块都编译此段代码的话则还是会有重复代码)
一般格式:
- #ifndef <标识>
- #define <标识>
- ...
- ...
- #endif
使得编译器可以根据这个名字是否被定义,再决定要不要继续编译该头文中后续的内容。
<标识> 在理论上来说可以是自由命名的,但每个头文件的这个<标识>都应该是唯一的。标识的命名规则一般是:
这个方法虽然简单,但是写头文件时一定记得写进去。
头文件
& 声明
& 定义
的规则header file
中是对于该模块接口的声明, 接口包括该模块提供给其它模块调用的外部函数及外部全局变量, 对这些变量和函数都需在 header file
中冠以 extern
关键字声明implementation file
开头冠以 static
关键字声明header file
中定义变量#include
其 header file
即可.❝如果工程很大, 头文件很多, 而有几个头文件又是经常要用的, 那么
header file
里面去, 比如写到 preh.hpreh.cpp
, 里面只一句话: #include "preh.h"
preh.c
, 在 project setting 里面设置 create precompiled headers
, 对于其他 c++ 文件, 设置 use precompiled header file