在比较大的项目中,如果需要使用全局变量,那么就需要注意一些全局变量声明、使用不当引起的问题了。

本篇文章主要内容有两个:普通全局变量、静态全局变量、全局常量。

1、普通全局变量:假设我们需要在多个不同的编译单元(比如两个.cc文件)中使用全局变量进行传值,如我们有如下三个源码文件:

main.cc:运行入口,有一个main函数,其中会打印出全局变量var的值;

  1. #include "def.h"
  2. #include  <iostream>
  3. using namespace std;
  4. int main()
  5. {
  6. cout<<var<<endl;
  7. return 0;
  8. }

def.cc:全局变量var的定义处;

  1. #include  "def.h"
  2. int var;    //可以赋初值,也可以这样

def.h: 全局变量var的声明处;

  1. #ifndef  _DEF_H
  2. #define _DEF_H
  3. extern int var;
  4. #endif

注意:

在linux里编译的时候def.cc和main.cc都要编译(我自己写的时候就是忘记编译def.cc了,傻傻的发现main.cc编译出错。。。);

在.h中用extern声明全局变量,在某一个.cc文件中定义该全局变量,且在定义处包含声明的.h头文件,这样保证该全局变量在整体上只定义一次(否则如果在.ht头文件中定义的话,编译时会遇到多重定义错误),然后再使用全局变量的其他编译单元的.cc文件中,只需包含该.h头文件即可;

extern 声明表示在此处引入外部定义变量的声明,而不是在本编译单元中再声明一个同名的局部变量;

2、静态全局变量:即使用static修饰的全局变量,他不能使用extern进行引入声明,即extern与static不可以一起使用;而且static全局变量与普通全局变量有很大不同,我们使用一个测试程序来说明;

def.h:定义static全局变量var以及fun函数的头文件;

  1. static  int  snum=22;
  2. static  int  sme;
  3. void fun();

def.cc:定义fun函数的源文件;

  1. #include "def.h"
  2. #include  <iostream>
  3. using namespace std;
  4. void fun()
  5. {
  6. snum=33;
  7. sme=3;
  8. cout<<snum<<", "<<sme<<endl;
  9. }

mod.h:输出全局变量值的另外一个头文件;

  1. #include "def.h"
  2. #include <iostream>
  3. using namespace std;
  4. void fun2()
  5. {
  6. cout<<snum<<", "<<sme<<endl;
  7. }

main.cc:执行入口;

  1. #include "def.h"
  2. #include "mod.h"
  3. #include <iostream>
  4. using namespace std;
  5. int main()
  6. {
  7. cout<<snum<<", "<<sme<<endl;
  8. fun();
  9. fun2();
  10. }

输出结果:

22,0

33,3

22,0

可以看出,调用了fun()之后,在fun2()中打印出来的值并没有改变,原因是:static修饰的全局变量的作用域只是其本身所在的编译单元(在本编译单元内更改生效),在其他单元中使用时,该变量会有新的内存地址,也就是说,每一个使用它的编译单元都给它开辟了单独的空间,并把它的初始值复制过来,这样如果某个单元中对它进行了修改,那么多个编译单元中它的值就可能不一样了;

注意:

static修饰的全局变量声明与定义是一体的,在头文件中声明了static全局变量,同时也是定义了它,不像普通的全局变量是分开的;

多个编译单元都包含static全局变量所在的头文件,不会引起重定义错误,因为每个编译单元都开辟了新的空间存储它;

3、const全局变量:const全局变量使用起来与普通全局变量一样,在.cc中定义并赋初值,在.h头文件中用extern进行声明,然后再需要使用的地方包含.h即可,在多个编译单元中其内存地址也不同(这一点与static全局变量类似),但是由于是常量,不能修改其值,所以即使内存地址不一样也没影响,值都一样。

参考致谢:http://blog.csdn.net/candyliuxj/article/details/7853938

C++全局变量在多个源代码文件中的使用的更多相关文章

  1. C语言:全局变量在多个c文件中公用的方法 [转]

    用C语言编写程序的时候,我们经常会遇到这样一种情况:希望在头文件中定义一个全局变量,然后包含到两个不同的c文件中,希望这个全局变量能在两个文件中共用. 举例说明:项目文件夹project下有main. ...

  2. VS开发】C中调用C++文件中定义的function函数

    [VS开发]C中调用C++文件中定义的function函数 标签(空格分隔): [VS开发] 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 精要一揽 C调用 ...

  3. 独立的js文件中不能使用EL表达式取值

    在独立的js文件中写了一个EL表达式取值,发现没有取到值,原因在于不能在独立的js文件中使用EL表达式,可以在jsp页面定义全局变量,然后在js文件中引用

  4. 效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中【附源代码下载】) 转

    效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中[附源代码下载])    本文目录: (一)背景 (二)数据库数据导入到Excel的方法比较   ...

  5. c语言头文件中定义全局变量的问题

    c语言头文件中定义全局变量的问题 (转http://www.cnblogs.com/Sorean/) 先说一下,全局变量只能定义在 函数里面,任意函数,其他函数在使用的时候用extern声明.千万不要 ...

  6. 今天在Mac机器上使用了Flex Builder编辑了一个源代码文件,保存后使用vim命令去打开时发现系统自动在每一行的结尾添加了^M符号,其实^M在Linux/Unix中是非常常见的,也就是我们在Win中见过的/r回车符号。由于编辑软件的编码问题,某些IDE的编辑器在编辑完文件之后会自动加上这个^M符号。看起来对我们的源代码没有任何影响,其实并不然,当我们把源代码文件Check In到svn之类

    今天在Mac机器上使用了Flex Builder编辑了一个源代码文件,保存后使用vim命令去打开时发现系统自动在每一行的结尾添加了^M符号,其实^M在Linux/Unix中是非常常见的,也就是我们在W ...

  7. C语言头文件中定义全局变量导致重复定义错误

    合作方升级SDK后,程序编译出现变量重复定义的错误,通过错误提示无法找到什么位置重复定义了,但确定是引入新SDK后才出现的错误,从SDK的头文件中查找,最终发现在头文件中定义了全局变量 我们的项目在多 ...

  8. c++多个文件中如何共用一个全局变量

    例子: 头文件:state.h   源文件:state.cpp 其它源文件:t1.cpp  t2.cpp  t3.cpp, 这些源文件都包含头文件state.h. 需要定义一个全局变量供这些源文件中使 ...

  9. extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”

    extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”

随机推荐

  1. eclipse里maven install时,报错提示jdk为无效的目标版本:1.7

    http://blog.csdn.net/wabiaozia/article/details/51733372 ************************************ 报错提示: [ ...

  2. Freemarker 入门示例(zhuan)

    http://cuisuqiang.iteye.com/blog/2031768 ************************************ 初步学习freemarker ,先做一个简单 ...

  3. zImage转换为uImage

    写个随笔,备忘! 拿到一个内核后,首先将其make为zImage,步骤: 1.将与要移植的系统的配置文件拷贝给.config cp xxx_xxx .config 2.修改Makefile,指定平台构 ...

  4. spring源码深度解析-2功能扩展

    容器功能的扩展ApplicationContext用于扩展BeanFactory中现有的功能.究竟多出了哪些功能,进一步探索.写法上:BeanFactory bf = new XmlBeanFacto ...

  5. vm 安装 vcenter 本主要记录选择l现有的受支持数据库

    1.将先决条件安装完毕. 安装 .NET3.5 全部下一步记录设置的密码.备忘.

  6. 解决xshell 中文乱码

    在xshell命令行里面 输入:  locale输出: LANG=zh_CN.UTF-8LC_CTYPE="zh_CN.UTF-8"LC_NUMERIC="zh_CN.U ...

  7. 最最最简单的轮播图(JQuery)

    html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  8. Visual Studio原生开发的10个调试技巧(二)

    来源:oschina 发布时间:2013-08-10 阅读次数:397 51   我以前关于Visual Studio调试技巧的文章引起了大家很大的兴趣,以至于我决定分享更多调试的知识.以下的列表中你 ...

  9. 《javascript高级程序设计》第六章 Object Creation VS Inheritance

    6.1 理解对象 6.1.1 属性类型 6.1.2 定义多个属性 6.1.3 读取属性的特性6.2 创建对象 6.2.1 工厂模式 6.2.2 构造函数模式 6.2.3 原型模式 6.2.4 组合使用 ...

  10. postgresql 触发器

    一.创建事件触发器 1.ddl_command_start - 一个DDL开始执行前被触发: 2.ddl_command_end - 一个DLL 执行完成后被触发: 3.sql_drop -- 删除一 ...