為什麼用EXTERN?
全局變量(外部變量)是在函數的外部定義的,它的作用域為從變量的定義處開始,到本程序文件的末尾。在此作用域內,全局變量可以為本文件中各個函數所引用。編譯時將全局變量分配在靜態存儲區。有時需要用extern來聲明全局變量,以擴展全局變量的作用域。如果外部變量不在文件的開頭定義,其有效的作用范圍只限於定義處到文件終了。如果在定義點之前的函數想引用該全局變量,則應該在引用之前用關鍵字 extern對該變量作外部變量聲明,表示該變量是一個將在下面定義的全局變量。有了此聲明,就可以從聲明處起,合法地引用該全局變量,這種聲明稱為提前引用聲明。extern關鍵字告訴編譯器,"這個變量可能定義在這個模塊或其它模塊中",一個extern聲明並沒有生成數據,它僅表明這個數據是共享的。這個變量必須是在別處定義過的,而且它只能定義一次.
一個extern的小例子
view plaincopy to clipboardprint?
#include <iostream>
using namespace std;
int max(int,int); //函數聲明
void main( )
{extern int a,b; //對全局變量a,b作提前引用聲明
cout<<max(a,b)<<endl;
}
int a=15,b=-7; //定義全局變量a,b
int max(int x,int y)
{int z;
z=x>y?x:y;
return z;
}
#include <iostream>
using namespace std;
int max(int,int); //函數聲明
void main( )
{extern int a,b; //對全局變量a,b作提前引用聲明
cout<<max(a,b)<<endl;
}
int a=15,b=-7; //定義全局變量a,b
int max(int x,int y)
{int z;
z=x>y?x:y;
return z;
}
運行結果如下:
15
在main後面定義了全局變量a,b,但由於全局變量定義的位置在函數main之後,因此如果沒有程序的第5行,在main函數中是不能引用全局變量a和 b的。現在我們在main函數第2行用extern對a和b作了提前引用聲明,表示a和b是將在後面定義的變量。這樣在main函數中就可以合法地使用全局變量a和b了。如果不作extern聲明,編譯時會出錯,系統認為a和b未經定義。一般都把全局變量的定義放在引用它的所有函數之前,這樣可以避免在函數中多加一個extern聲明聲明:在某個頭文件1.h(可以在同一文件中或同一程序的不同文件中出現多次 );
2. 在多文件的程序中聲明外部變量
如果一個程序包含兩個文件,在兩個文件中都要用到同一個外部變量num,不能分別在兩個文件中各自定義一個外部變量num。正確的做法是:在任一個文件中定義外部變量num,而在另一文件中用extern對num作外部變量聲明。即
extern int num;
編譯系統由此知道num是一個已在別處定義的外部變量,它先在本文件中找有無外部變量num,如果有,則將其作用域擴展到本行開始(如上節所述),如果本文件中無此外部變量,則在程序連接時從其他文件中找有無外部變量num,如果有,則把在另一文件中定義的外部變量num的作用域擴展到本文件,在本文件中可以合法地引用該外部變量num。分析下例:
file1.cpp file2.cpp
extern int a,b; int a=3,b=4;
int main( ) ┆
{cout<<a<<″,″<<b<<endl;
return 0;
}
用extern擴展全局變量的作用域,雖然能為程序設計帶來方便,但應十分慎重,因為在執行一個文件中的函數時,可能會改變了該全局變量的值,從而會影響到另一文件中的函數執行結果。
另一個很好的例子
定義:在任何一個源文件x.cpp(只能定義一次!#include<1.h>) ;
使用:要使用這個全局變量,只要包含1.h就行了。
在全局域中定義的對象 如果沒有指定顯式的初始值 則該存儲區被初始化為 0 因此下面兩個定義中 var1和 var2有相同的初始值 0
int var1 = 0;
int var2;
關鍵字extern為聲明但不定義一個對象提供了一種方法 實際上它類似於函數聲明承諾了該對象會在其他地方被定義 或者在此文本文件中的其他地方 或者在程序的其他文本文件中 例如
extern int i;
對程序來說是一個 保證 表示在其他某個地方存在一個如下所示的定義
int i;
extern聲明不會引起內存被分配 它可以在同一文件中或同一程序的不同文件中出現多次 典型情況下 全局對象的聲明只在公共的頭文件中出現一次
當一個程序文件需要引用這個全局對象時 它可以包含這個頭文件
// 頭文件
extern int obj1;
extern int obj2;
// 文本文件
int obj1 = 97;
int obj2;
既指定了關鍵字 extern 又指定了一個顯式初始值的全局對象聲明將被視為該對象的定義 編譯器將會為其分配存儲區 而且該對象後續的定義都被標記為錯誤 例如
extern const double pi = 3.1416; // 定義
const double pi; // 錯誤: 重復定義 pi
關鍵字 extern也可以在函數聲明中指定 惟一的影響是將該聲明的隱式屬性 在其他地方定義 變為顯式的 這樣的聲明有下列形式
extern void putValues( int*, int )
一般是在一個源文件如1.cpp裡定義變量, 如 CString str;(這是定義,只能有一個定義)
在其他文件中要用使用時,可以在頭文件如1.h裡聲明: extern CString str;(聲明,可以有多處),然後include "1.h"就行了,不用再定義,否則定義重復,也可以不用聲明;include "1.h"中已經聲明。
例如:
---------------------
1.h 源碼:
extern CString str;//這是聲明,表示這個變量在其他文件裡有定義,這裡是1.cpp.一定要有個文件裡有它的定義。
......
---------------------
1.cpp 源碼:
include "1.h"
......
CString str; // 定義
......
---------------------
2.cpp 源碼
include "1.h" // 聲明了變量CString str,並且在 1.cpp裡定義了
str = "......"; // 直接使用,include "1.h"中已經聲明。
---------------------
.h文件 裡若沒有extern ,表示定義;
.cpp文件裡有相同定義就是重復定義了;
.h文件裡加了extern 後,表示聲明,要有地方有它的定義(實現)。