extern关键字

来源:互联网 发布:淘宝皮草外套新款 编辑:程序博客网 时间:2024/06/07 20:18

微笑吐舌头extern关键字会提升变量或者函数的逼格,使得它们可以跨文件被访问。话虽然是这么说,使用这个关键字必须要注意一些东西。

微笑吐舌头首先,你得在cpp文件里面实现这些全局变量和全局函数,这是最基本的,然后只需要在需要用到这些变量和函数的文件里声明一下,用extern修饰声明,这样弄完之后就可以随意使用这些全局变量和全局函数了。请不要为编译器担心,担心它们找不到这些东西,只要你实现了,不怕编译器找不到。

微笑吐舌头别的文件里写一堆的extern声明显得特别不专业,也显得代码十分臃肿,有没有好的做法呢?有的。

微笑吐舌头我们一般把所有的全局变量和全局函数都放在一个*.cpp文件里面,然后用一个同名的*.h文件包含所有的函数和变量的声明。用法的示例如下:

[cpp] view plain copy
 print?
  1. /*Demo.h*/  
  2. #ifndef _DEMO_H_  
  3. #define _DEMO_H_  
  4.   
  5. extern int a;  
  6. extern int b;  
  7. int add(int a, int b);  
  8.   
  9. #endif  
  10. /** 
  11. //下面的写法也可以 
  12. #pragma  once 
  13. extern int a; 
  14. extern int b; 
  15. */  
[cpp] view plain copy
 print?
  1. /*Demo.cpp*/  
  2. #include "Demo.h"   
  3. int a = 10;  
  4. int b = 20;  
  5.   
  6.  int add(int l, int r)  
  7. {  
  8.     return l + r;  
  9. }  
[cpp] view plain copy
 print?
  1. /*main.cpp*/  
  2. #include "Demo.h"  
  3. #include <iostream>  
  4. using namespace std;  
  5.   
  6. void main()  
  7. {  
  8.     cout << "a = " << a << ", b = " << b << endl;  
  9.   
  10.     int c = add(1, 2);  
  11.     printf("c = 1 + 2 = %d \n", c);  
  12.     system("pause");  
  13. }  

生气生气运行结果如下:


生气生气这样处理之后只需要到用到的地方加入#include"Demo.h"一句即可,很方便吧!这么干方便了这些变量和全局函数的管理。

生气生气下面是关于extern关键字的一些说明:

微笑吐舌头(1)extern声明外部函数

生气生气在A.cpp中使用B.cpp中的函数,需要extern声明。定义的形式类似于:

extern  int  a;

生气生气这里需要注意定义和声明的区别,extern  int  a = 10;属于定义了。

[cpp] view plain copy
 print?
  1. /*Demo.h*/  
  2. #ifndef _DEMO_H_  
  3. #define _DEMO_H_  
  4.   
  5. extern int a = 10;  
  6. extern int b = 20;  
  7. int add(int a, int b);  
  8.   
  9. #endif  
  10. /** 
  11. //下面的写法也可以 
  12. #pragma  once 
  13. extern int a; 
  14. extern int b; 
  15. */  
[cpp] view plain copy
 print?
  1. /*Demo.cpp*/  
  2. #include "Demo.h"  
  3. int a = 10;  
  4. int b = 20;  
  5.   
  6.  int add(int l, int r)  
  7. {  
  8.     return l + r;  
  9. }  
[cpp] view plain copy
 print?
  1. /*main.cpp*/  
  2. #include "Demo.h"  
  3. #include <iostream>  
  4. using namespace std;  
  5.   
  6. void main()  
  7. {  
  8.     cout << "a = " << a << ", b = " << b << endl;  
  9.   
  10.     int c = add(1, 2);  
  11.     printf("c = 1 + 2 = %d \n", c);  
  12.     system("pause");  
  13. }  

难过委屈这么干肯定是编译不通过的,因为存在重定义,#include"Demo.h"这一句是单纯的代码替换,在Demo.cpp和main.cpp里替换之后你自然发现全局变量被定义了两次,肯定会报错。一句话,声明可以拷贝n次,但是定义只能定义一次

 

微笑吐舌头(2)extern声明全局变量

难过委屈在A.cpp中使用B.cpp中的全局变量,需要extern声明。

难过委屈extern关键字的作用是告诉编译器,在某个cpp文件中,存在这么一个函数/全局变量。

安静鄙视函数的声明类似于:

extern  int  sum(int, int);

难过委屈函数的声明语句中,关键字extern可以省略,因为全局函数默认是extern类型的,因此也就出现了Demo.h中的状况。

 

难过委屈虽然用extern声明了变量和函数之后,在别的文件里就随意使用了,但是你也千万别忘了书写变量和函数的实现,否则就会出现无法解析的外部符号,编译无法通过。

鄙视鄙视还有一件很有趣的事情,如果你将前面的Demo.cpp改为Demo.c的话,编译器会告诉你说找不到变量和函数是无法解析的外部符号,怎么办呢?

大笑吐舌头之所以会出现这样的原因,是因为c++编译器和c编译器差异性的问题,C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数的情况,我们是在main.cpp文件里包含了Demo.h也就是在main.cpp里面声明了这么一些变量和函数(代入即可),main.cpp里面的声明会被c++编译器成处理中间的名称,而Demo.c里面的实现会被c编译器处理,两者处理的差异性(详情可以看我后面提供的链接),导致问题多多。总之处理之后.c文件的实现和.cpp里面的声明不一致了,这也是导致找不到的原因,这个时候就必须用extren "C"了,告诉c++编译器,请保持我的名称,不要给我生成用于链接的中间函数名。

鄙视鄙视我们将Demo.h里面的东西改一下写法即可:

[cpp] view plain copy
 print?
  1. /*Demo.h*/  
  2. #ifndef _DEMO_H_  
  3. #define _DEMO_H_  
  4.   
  5. #ifdef  __cplusplus  
  6. extern "C" {  
  7. #endif  
  8.   
  9.     extern int a;  
  10.     extern int b;  
  11.     int add(int a, int b);  
  12.   
  13.   
  14. #ifdef  __cplusplus  
  15. }  
  16. #endif  
  17.   
  18. #endif  
[cpp] view plain copy
 print?
  1. /*Demo.c*/  
  2. //#include "Demo.h"  
  3. #include <stdio.h>  
  4. int a = 10;  
  5. int b = 20;  
  6.   
  7.  int add(int l, int r)  
  8. {  
  9. #ifndef __cplusplus  
  10.     printf("这是一个c程序!\n");  
  11. #endif // !_cplusplus  
  12.   
  13. #ifdef __cplusplus  
  14.     printf("这是一个c++程序!\n");  
  15. #endif // !_cplusplus  
  16.     return l + r;  
  17. }  
[cpp] view plain copy
 print?
  1. /*main.cpp*/  
  2. #include "Demo.h"  
  3. #include <iostream>  
  4. using namespace std;  
  5.   
  6. void main()  
  7. {  
  8. #ifdef __cplusplus  
  9.     cout << "这是一个c++程序" << endl;  
  10. #endif  
  11.   
  12. #ifndef __cplusplus  
  13.     cout << "这是一个c程序" << endl;  
  14. #endif  
  15.     cout << "a = " << a << ", b = " << b << endl;  
  16.   
  17.     int c = add(1, 2);  
  18.     printf("c = 1 + 2 = %d \n", c);  
  19.     system("pause");  
  20. }  

再见再见运行结果如上图,特别要声明一下__cplusplus,前面是两个_,在.c文件没有定义__cpluspluscpp文件定义了__cplusplus,一不小心将__cplusplus写成了_cplusplus会出现什么呢?就是我下面的情况了。

[cpp] view plain copy
 print?
  1. /*Demo.h*/  
  2. #ifndef _DEMO_H_  
  3. #define _DEMO_H_  
  4.   
  5. #ifndef  _cplusplus  
  6. extern "C" {  
  7. #endif  
  8.   
  9.     extern int a;  
  10.     extern int b;  
  11.     int add(int a, int b);  
  12.   
  13.   
  14. #ifndef  _cplusplus  
  15. }  
  16. #endif  
  17.   
  18. #endif  
[cpp] view plain copy
 print?
  1. /*Demo.c*/  
  2. //#include "Demo.h"  
  3. #include <stdio.h>  
  4. int a = 10;  
  5. int b = 20;  
  6.   
  7.  int add(int l, int r)  
  8. {  
  9. #ifndef _cplusplus  
  10.     printf("这是一个c程序!\n");  
  11. #endif // !_cplusplus  
  12.   
  13. #ifdef _cplusplus  
  14.     printf("这是一个c++程序!\n");  
  15. #endif // !_cplusplus  
  16.     return l + r;  
  17. }  
[cpp] view plain copy
 print?
  1. /*main.cpp*/  
  2. #include "Demo.h"  
  3. #include <iostream>  
  4. using namespace std;  
  5.   
  6. void main()  
  7. {  
  8. #ifdef _cplusplus  
  9.     cout << "这是一个c++程序" << endl;  
  10. #endif  
  11.   
  12. #ifndef _cplusplus  
  13.     cout << "这是一个c程序" << endl;  
  14. #endif  
  15.     cout << "a = " << a << ", b = " << b << endl;  
  16.   
  17.     int c = add(1, 2);  
  18.     printf("c = 1 + 2 = %d \n", c);  
  19.     system("pause");  
  20. }  

再见再见说实话,结果我挺震惊的,在Demo.c文件中定义的函数跑出一个“这是一个c程序”,也没什么,在一个cpp文件中的函数跑出一个“这是一个c程序”,我就很震惊了,原因我也不清楚,不过基本就是上面的解决方案了,最后说一下不在Demo.c包含#include"Demo.h"的原因,因为在extern “C”不是为C所支持,其实也不算吧!

再见再见因为网上说.c文件没有定义_cplusplus而cpp文件定义了_cplusplus,如果真是这样在Demo.c包含#include"Demo.h"也不会出现问题,可是不知道是我的编译器原因还是什么的,c文件和cpp文件都没定义_cplusplus,因此有可能Demo.c包含#include"Demo.h"出现问题,因为为了能在cpp文件中使用,Demo.h文件里我一般要写成#ifndef_cplusplus,此时若Demo.c包含#include"Demo.h",恰好c文件中也没有定义_cplusplus,那么extern “C”就暴露出来了,自然会错。


再见再见ps:关于extern和extern “C”,有更好的讲解,我就不班门弄斧了。

再见再见链接:http://pan.baidu.com/s/1o6CACga 密码:xefl