原文地址:
在上一节,main文件已经乱作一团,这有个变量定义,那又有个extern什么的,已经有点看不懂了。
于是,我们来研究一下变量定义和extern 声明的方法吧。
等等,在这先对上一章做一下概括吧。
・(这次设计的场景)全局变量,定义在主文件 main.cpp 里面了
・ 从其他的文件引用这里的全局变量的时候,在其他文件里要用extern声明。
就是酱紫呢。
但是,在主文件里定义,然后在其他文件里使用extern调用同样的变量时,感觉是个效率比较低的方法。
那么,我们在所有文件里都调用同一个头文件,在这个头文件里面,
根据在哪里被调用写个条件分支,然后给出适当的声明。如果这样做的话,效率就比较高了。
稍微看一下下面这段程序吧。
——————————————————————————————————————————————————————
#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL extern
#endif
GLOBAL int img;
————————————————————————————————————————————————————————
(以下这段翻译里的“调用”,指的是GLOBAL int img; 这行代码被预处理后实际变成的样子。也就是说,这个“调用”指的是预处理操作)
这段代码的含义是,
如果定义了GLOBAL_INSTANCE的话,GLOBAL就被替换成空白
如果没有定义GLOBAL_INSTANCE的话,GLOBAL就被替换成extern
然后,我们这样写
GLOBAL int img;
会怎么样呢?是的,这样的话,用和不用extern, 就被区分开了。
因为从main.cpp调用的时候,必须是定义,所以不加extern 。
也就是说,定义了GLOBAL_INSTANCE之后,调用就很方便了。(自动去掉GLOBAL)
另一方面,从其他文件调用这个img全局变量,我们得加上extern。
也就是说,不定义GLOBAL_INSTANCE,也啥都不用写,很方便。(自动会把GLOBAL变成extern)
这里我们看一下main 文件的最上面吧。那里写着
#define GLOBAL_INSTANCE
#include "../include/GV.h"
这里定义了GLOBAL_INSTANCE,调用的时候,就是对变量的定义。
其他文件没有定义这个,调用的时候,就会加上extern.
这样,就实现了从其他文件来调用main里定义的全局变量的方式。
这样的话还有一点。已经实现的函数被其他文件调用的时候,同样也需要在main文件里声明一次。
声明了extern的话,在程序实现的地方和调用的地方都有好处。
在main文件里只要用extern声明了,不管在哪里实现的,可以调用到。(此处翻译有点不够到位,求指正)
然后,在根据不同的条件,在 GV.h 的引入 function.h也用上述同样的GLOBAL来声明看看吧。
其实,看了就应该很容易明白了,像下面这样添加上去吧。
————————————————————————————————————————————————————————
//--function.h改动--
//graph.cpp
//描画 main
GLOBAL void graph_main();
//key.cpp
//现在的键位输入状态
GLOBAL int GetHitKeyStateAll_2();
//根据键的序号,返回输入的状态
GLOBAL int CheckStateKey(unsigned char Handle);
//laod.cpp
//数据载入
GLOBAL void load();
————————————————————————————————————————————————————————
————————————————————————————————————————————————————————
//--GV.h改动--
#include "../../../include/DxLib.h"
#include "define.h"
#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL extern
#endif
#include "function.h" //函数声明
//图片变量声明
GLOBAL int img_ch[2][12]; //自机的图片9张 X2(变身用)
//构造体变量声明
GLOBAL ch_t ch; //构造体数据声明
————————————————————————————————————————————————————————
然后在「main.cpp」「graph.cpp」「load.cpp」的在这些变量的定义部分,把extern 都去掉。
编译一下,如果没有错误,结果和第四节一样的话,就OK了。
以后,添加全局变量,就往GV.h 里面添加,
需要在 main 文件调用,在其他文件声明的方法,就往 function.h 里面添加吧。
(注:看得出来,这章主要是总结集中了全局变量和方法的声明和调用的方法。熟悉C/C++的应该很容易懂吧)
(我是还没怎么看明白,所以有些地方翻译的没能很好表达清楚意思。等我把第四章和第五章的程序改动读一遍,再来这修改一下吧)
研究了一下项目预处理之后的文件,大概推断出了#include 和上面 #ifnef 这些的作用了。
首先我们理一下这一章和上一章的变动。
原先,是在main 里面定义了两个全局变量。然后用extern 声明需要写在其他文件里面的函数。
同时,其他文件要调用main里定义的全局变量也要加extern。弄得很乱。
(补充一点关于extern,其实main里调用其他函数时写的声明,可以去掉extern的。
但其他文件用extern声明main里面定义的,这个extern不能去掉,不然就重复定义了)
修改后,
GV.h 加上ifndef 判断,然后,函数声明都加上GLOBAL放到 function.h 里面,include 到GV.h中。全局变量也加上GLOBAL,在GV.h里声明。
相当于,所有函数和全局变量,都加上GLOBAL声明,放在GV.h里面。
其他文件包含GV.h了,就可以去掉对 全局变量单独写引用声明了。
然后,
由于main.cpp定义了GLOBAL_INSTANCE , 预处理的时候,GV.h全部包含进来后,会去掉extern。这样,变量就变成定义,函数去掉extern也还是声明。
其他文件没有定义GLOBAL_INSTANCE ,预处理GV.h全部包含进来后,会保留extern。这样就 声明了定义在别处的 全局变量和函数。
本人CSDN博客目录: