全局變量 若有所思

文件結構如下: main.h ,main.cpp, ddraw.h, ddraw.cpp 大致問題如下,在main.h中定義了全局變量,然後在main.cpp以及ddraw.cpp中都要使用到它,所以都包含了此頭文件,結果 導致錯誤: ddraw.obj : error LNK2005: xxxx already defined in main.obj Debug/S.exe : fatal error LNK1169: one or more multiply defined symbols found Error executing link.exe. 表示重複定義了。 一時也沒有弄清楚編譯頭緒,關鍵在於,全局變量(以下稱爲global)僅僅就定義了一次,而別的函數只是對於該 頭文件進行了引用。 網上查找資料,最通俗的和最深奧的莫過於以下兩張帖子: http://topic.csdn.net/t/20050525/17/4035191.html http://blog.csdn.net/xcntime/archive/2009/04/25/4122982.aspx 不過都沒有說到我發生的問題的實質上,由於頭文件都加入了預編譯命令 pragma once (等價於ifndef……define……endif這兩個沒有去邊,一個是宏,另外一個是預編譯命令) 然而,解決問題的方法倒是比較容易: 方法1、將global的變量定義寫在cpp中,將 extern type global 寫在頭文件中,其他需要引用到該變量的文件包含該頭文件即可(無需再次聲明extern)則此時,無論其他文件如何包含都不會出現問題xxxx already defined 爲什麼呢? 原因在於,在編譯階段,如果系統遇到關鍵字extern,會把該變量用作聲明(聲明是不會形成實體的),extern表明:變量global已經在項目中 被定義到了,只要在各個文件中查找便行了。此時,包含該頭文件的各個文件生成的obj中,不會實例化變量global(也就是開闢存儲空間),所以,global真正 被實例化的時候只有在cpp中自己唯一一次被定義的時候,因爲編譯該變量的cpp並沒有被引用的文件包含,所以,實例只會生成一次,故而不會出現重複定義的錯誤。 方法2: 將global的定義寫在h文件中(但必須通過相應的cpp文件將此頭文件包括並生成相應obj),其他需要引用該變量的文件直接說明 extern type global,但是! 絕對不能include 該頭文件。 原因,剛剛說了,使用extern關鍵字時候,編譯器不會爲相應對象生成實例,所以在相應obj中中找不到global的實例,因爲global只在h文件中定義了 ,也就是只會在包含h文件的obj中實例化一次,其他地方引用的話會通過extern關鍵字找到這個位置,所以可行。 ****小貼士,在同一個項目中,extern關鍵字聲明的變量或者函數,並不需要inlcude該項目下相應的頭文件,因爲一旦extern所修飾的函數和變量被定義過後,則該符號必然是唯一的,則並不需要指定出在那個文件中出現過它的定義。 那麼,回到剛剛問題的最開始,爲什麼會出現error LNK2005: xxxx already defined in main.obj呢? 頭文件中定義了該變量,並且其他所有需要引用到該變量的文件都include了該頭文件,所以,每當生成各個相應的obj對象的時候, 該頭文件中定義的global都會試圖生成一次實例,然後,在編譯器檢查的時候,一旦發現該變量已經被定義過一次,當另外包含該頭文件的對象需要再次定義生成實例時候,就會報出重複定義的錯誤。 注意,定義和聲明的區別 這裏需要的是“聲明”,不是“定義”!根據C++標準的規定,一個變量是聲明,必須同時滿足兩個條件,否則就是定義: (1)聲明必須使用extern關鍵字;(2)不能給變量賦初值 所以,下面的是聲明: extern int a; 下面的是定義 int a; int a = 0; extern int a =0;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章