關於頭文件中定義的全局變量的包含

 在頭文件中定義了一個變量,若另一個文件包含此文件則會再產生一個相同變量的定義,在linux環境中編譯時會發生如

menu.o:(.sbss+0x0): multiple definition of `is_refresh_living_time_thread_created'
main.o:(.sbss+0x0): first defined here

的錯誤,要在包含該文件的文件中使用此變量應該聲明全局變量“extern int is_refresh_living_time_thread_created”,或者叫作“通過extern關鍵字擴展全局變量is_refresh_living_time_thread_created的作用範圍(即擴展到包含該文件的文件中)”;這和頭文件中的函數聲明不同,因爲函數在頭文件中僅僅是聲明,聲明可以有多個,但是無論是函數還是變量定義都只能有一個,否則就會發生重複定義的錯誤。

      頭文件中變量如果沒有初始化就是聲明;初始化了就是定義,此時被包含之後會發生重複定義的錯誤。

      並不是所有的變量都能用extern聲明,只有全局變量並且沒有被static 聲明的變量才能聲明爲extern. 所以如果你不想自己源文件中全局的變量被其他文件引用,你就可以給變量加上static聲明.

     

    很多初學者,對變量的定義和聲明分不請,只知道有這回事。下面對這兩個概念詳細說明下:

變量的定義:爲變量分配存儲空間,同時指明變量的類型和名字。另外變量的初始化,就是在變量的定義出給出值。

變量的聲明:它主要向程序聲明變量的類型和名字。定義也是聲明(這是許多人搞不清楚的地方),那既然變量的定義就是聲明,爲啥還要再多出來個變量的聲明這個概念,直接就用變量的定義不是就可以了?

其實不然,C++中有個關鍵字是用來聲明變量的,它是extern。它聲明一個變量卻不定義它,即不在給它一個存儲空間。

例如:int i;//定義也可以說是聲明

extern int i;//這就是單純的聲明

注意:在C++語言中,變量有且只能有一次定義,但是可以聲明多次,使用變量前必須定義或聲明。

這依然沒有說明這個變量聲明有什麼作用,下面就舉個例子說明變量聲明的作用

假設我們在文件1.cpp中定義了一個全局變量bufsize,文件1.cpp中當然可以訪問它,如果我想在另外一個文件2.cpp中訪問這個全局變量,這時候需要在文件2.cpp中聲明這個變量。

//1.cpp

int bufsize;

//2.cpp

extern int bufsize;

這說的是非const的全局變量,如果是const的全局變量,如果想要被其他文件訪問,需要在定義的時候,加上extern關鍵字,表示它可以在其他文件被聲明使用的,即可以被整個程序(一個程序可能包括多個源文件)訪問,否則的話,這個變量只能在它被定義的文件裏面被訪問,其他文件不能訪問。

//1.cpp

extern const int bufsize=10;

//2.cpp

extern const int bufsize;

這時候你也許會問,爲什麼非const變量定義的時候爲什麼沒有extern?

答:非const變量默認爲extern。而const變量如果想要在其他文件裏被訪問,必須顯示的指定它爲extern。

看完這個你會對變量的聲明和定義有了個新的理解^-^

http://hi.baidu.com/huifeng00/blog/item/977dd653f68507858c54308b.html

 

今天看C++ Primer關於頭文件定義的一節,其中說到,頭文件應用於聲明而不是用於定義。其實,C++標準並沒有規定頭文件中不能定義 變量,只不過如果在頭文件中定義變量,而該頭文件又被多次包含的話,會造成變量的重新定義。
        這裏還涉及到另一個問題,需要提前說明,即使用預處理器避免多重包含。這裏的多重包含指的是同一個文件直接或者間接的包含一個頭文件多次,例如a.h包含b.h,a.cpp同時包含a.h和b.h,a.cpp就兩次包含了b.h。但由於b.h中具有避免多重包含的措施,a.cpp中還是隻包含了b.h一次。而包含的意思其實就是在預處理階段用被包含文件的內容代替此包含語句。
        回到頭文件定義變量的問題上,如果在頭文件中定義了變量,避免多重包含的措施只能避免該頭文件在同一個編譯單元內被包含一次,在不同的編譯單元內還是會被多次包含的,這樣就造成了變量的重複定義。
        但是也有例外,如果const對象在編譯時可以確定其值,可以將其放在頭文件中定義。這麼做是有原因的——const對象默認情況下是定義該變量的文件的局部變量,這樣即使此頭文件被多個包含,都不會在包含這些文件中重複定義此變量,所有對於這個const對象的引用全都指向在頭文件中定義的對象。如果在const對象定義的時候聲明extern,const對象就變得和普通非const對象一樣,從而失去此特性(非const對象的默認屬性爲extern)。
        C++中的很多用法都不是標準C++規定的,但是由於各種原因,已經是約定俗成或是慣常用法,至於原因以及除此之外的其他用法完全可以不必深究,否則很容易鑽牛角尖!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章