1. 程式人生 > >C++的全域性變數,靜態全域性變數,常全域性變數定義與宣告

C++的全域性變數,靜態全域性變數,常全域性變數定義與宣告

標頭檔案中變數如果沒有初始化就是宣告;初始化了就是定義。在C++語言中,變數有且只能有一次定義,但是可以宣告多次,使用變數前必須定義或宣告。

再說到這些變數的宣告與定義前,要知道這些變數的連結性:

外部全域性變數                  外部連線性   可以被extern

靜態全域性變數(static)  內部連線性   不能被extern

常全域性變數(const)      內部連線性  在之前加上extern就變成了外部連線性,就可以被其他的檔案extern了

宣告:(可以放在標頭檔案)沒有開闢記憶體的定義,型別定義,比如類的定義,結構體的定義,它是定義一個數據型別而已

定義:(不可放在標頭檔案)開闢了記憶體的定義,資料定義,比如類物件定義,變數定義

一般來說:

不分配記憶體的,放在標頭檔案
分配記憶體的放在cpp檔案,防止重複定義,當然也要看變數的連線性,內部連線性的可以放在標頭檔案定義。

  變數、函式、類,在使用之前都必須宣告,包含標頭檔案,如果a.h包含了b.h,在a.h裡面就對b.h裡面的宣告重新聲明瞭,這也是不能在標頭檔案裡面定義變數與函式的原因(防止重複定義),當然內部連結性的變數和行內函數除外。

       C++是不允許在標頭檔案裡定義一個外部全域性變數(宣告可以,比如在原始檔定義,在標頭檔案extern宣告,像int a;這樣不算宣告,是定義,全域性變數預設賦值0),因為當這個標頭檔案被多個別的檔案(.cpp或.h)包含的時候,會重複定義這個全域性變數,而外部

全域性變數是外部連線性,別的檔案可以互相訪問地址,這個與變數有且只能有一次定義(單一定義規則)矛盾,會造成編譯出錯,即使你在其他的檔案裡使用extern都不行,因為是其他檔案包含這個定義了外部全域性變數的標頭檔案。若是真的需要外部全域性變數,可以在原始檔定義一個外部全域性變數,在該原始檔的標頭檔案extern宣告這個變數,或者別的包含這個標頭檔案的檔案裡extern宣告這個變數,這樣變數只是在原始檔你定義一次,其他地方的都只是宣告,呼叫的地址還是那個定義了的原始檔裡面開闢的------如:b.h,c.h都包含了a.h,這時候可以在a.cpp裡面定義全域性,在a.h檔案extern下就行,這樣b.h,c.h就都能用了,或者在b.h,c.h以及他們的原始檔extern也可以。

對於static,const全域性變數,則可以定義在標頭檔案裡,因為它們的連線性為內部,它們的地址只有在本檔案裡訪問,即使這個標頭檔案被其他的檔案(.cpp或.h)包含,雖然重複定義,  c++ primer裡講的const變數定義時預設為檔案的區域性變數(內部連線性),當頭檔案中定義了const變數後每個包含該標頭檔案的檔案都有了自己的const變數。這與單一定義規則不矛盾,static也是同樣,但是const的連線性可變,在const變數前面加上extern後,就變成全域性變數,外部連線性,這時候要注意包含的問題。  而在.cpp檔案裡定義的const或者static變數,是不可以被別的檔案訪問的。(注意.h    .cpp等之間的包含關係)--------------------------------extern用於互不包含的檔案裡,或者被包含的檔案。
包含意味著重新定義,但是對於互不包含的檔案不可以定義同名的外部全域性變數,外部全域性變數屬於外部連線性,這樣就導致了重定義!當然加上static或者const就可以,這裡有個全域性儲存區的區分------http://blog.csdn.net/u010177010/article/details/50737429,內部連結的變數地址所在的儲存區跟外部連結所在的儲存區是不同的,但是都屬於全域性儲存區!

   對於static,const全域性變數,如果在兩個互不包含的檔案裡定義了相同的變數,第三個檔案包含了這兩個檔案,就會出錯,因為包含意味著重定義,同個記憶體塊不可能有兩個相同名字的記憶體。

總之,編譯是否出錯,看的是  變數的連線性以及是否重定義