extern与const

来源:互联网 发布:淘宝如何做主图 编辑:程序博客网 时间:2024/06/05 21:15

     最近看C++,遇到一个问题,C和C++中const的区别。然后各种查资料,看到一篇文章讲的不错,URL如下:const在c/c++中的区别   其中,有这么一段程序:

<span style="font-size:14px;">//*******************************C++代码**********************************//header.hconst int test = 1;</span>
<span style="font-size:14px;">//test1.cpp#include <iostream>#include "header.h"using namespace std;int main(){    cout << "in test1 :" << test << endl;}</span>
<span style="font-size:14px;">//test2.cpp#include <iostream>#include "header.h"using namespace std;void print(){    cout << "in test2:" << test << endl;    }</span>
以上代码编译连接完全不会出问题,但如果把header.h改为:
extern const int test = 1;
则会出问题,我就想不通了,虽然有解释,但是,还是看不懂。当然,大神们一看就懂的就别浪费时间了。

其实这个问题得先从全局变量说起。我一直搞不清楚全局变量是作用域是整个project还是仅仅在当前的文件。

在处理这个问题的时候,发现,其实不是那么简单,在这个文章中C++中变量的作用域与生命周期

讲的非常清楚,如下是原话,我直接引来:


全局变量

  • 作用域:全局作用域(全局变量只需在一个源文件中定义,就可以作用于所有的源文件。)
  • 生命周期:程序运行期一直存在
  • 引用方法:其他文件中要使用必须用extern 关键字声明要引用的全局变量。
  • 内存分布:全局数据区
  • 注意:如果在两个文件中都定义了相同名字的全局变量,连接出错:变量重定义

也就是说,一个全局变量,他真正能起作用的是它所在的源文件中,在这个文件中,你可以使用它,如果允许,你还可以修改它等等,

但是,从整个project的角度来看,这个全局变量在同一个project的其他源文件是不能直接使用的,会出现“一个或多个符号重复”

也就是说,其他文件知道这个全局变量的存在,可以看到它,但是不能直接用,典型的占着茅坑不拉屎,只有你用extern关键字将其

引到其他源文件的时候,才能用。

假设我们在全局定义一个const变量:const int i=1;

接下来说上边的const,首先先明白,当一个变量由const修饰时,那么这个变量的作用域就有点类似static修饰的变量了,注意,我这只是说作用域,

其他方面差别还是很大的。const变量在C++中是内连接,内连接的原理我不懂,但是从作用域上说,定义在全局的const变量 i 仅仅是所在源文件的全局变量,

不仅只能在源文件中用,对其他文件也不可见,所以其他文件可以放心大胆的定义 i。


但是const变量加上extern,那就不一样了。说到这,就得批评一下前文中写的extern的作用有两条,我觉得是三条。

先看有文章说的两条:

extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。

      也就是说extern有两个作用,第一个,当它与"C"一起连用时,如: extern "C" void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的,C++的规则在翻译这个函数名时会把fun这个名字变得面目全非,可能是fun@aBc_int_int#%$也可能是别的,这要看编译器的"脾气"了(不同的编译器采用的方法不一样),为什么这么做呢,因为C++支持函数的重载啊,在这里不去过多的论述这个问题,如果你有兴趣可以去网上搜索,相信你可以得到满意的解释!
    第二,当extern不与"C"在一起修饰变量或函数时,如在头文件中: extern int g_Int; 它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块活其他模块中使用,记住它是一个声明不是定义!也就是说B模块(编译单元)要是引用模块(编译单元)A中定义的全局变量或函数时,它只要包含A模块的头文件即可,在编译阶段,模块B虽然找不到该函数或变量,但它不会报错,它会在连接时从模块A生成的目标代码中找到此函数。


第一条无异议,但是第二条就有问题了。首先extern是可以修饰变量,将其扩展成全局变量的,此时,在全局区 extern int i = 0; 与int i = 0; 是一样的,但是对于const 就不一样了。extern const int i = 0; 此时,i 对其他源文件是可见的了,其他源文件是不能再拿i 去定义其他的东西。此所谓extern的第二个作用。第三个作用就是用来说明源文件中出现的extern修饰的变量定义在别的源文件中,提示编译器到其他源文件去查找。

说到这,我觉得,上边的问题也就明白了。test1.cpp中将会出现一个声明,声明const变量test,这个是对其他源文件可见的,也就对test2.cpp可见,此时,test2.cpp中也声明const变量test,重复声明,自然出错。


0 0
原创粉丝点击