C++中聲明與定義的區(qū)別(從鏈接角度分析)_第1頁(yè)
C++中聲明與定義的區(qū)別(從鏈接角度分析)_第2頁(yè)
C++中聲明與定義的區(qū)別(從鏈接角度分析)_第3頁(yè)
C++中聲明與定義的區(qū)別(從鏈接角度分析)_第4頁(yè)
C++中聲明與定義的區(qū)別(從鏈接角度分析)_第5頁(yè)
已閱讀5頁(yè),還剩3頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、c+學(xué)了這么多年你知道為什么定義類時(shí),類的定義放在.h文件中,而類的實(shí)現(xiàn)放 在cpp文件屮。它們?yōu)槭裁茨軌蜿P(guān)聯(lián)到一起呢?你知道什么東西可以放在h文件屮, 什么不能。什么東西又可以放在cpp文件中。如果你忘記了或是壓根就不明白,那 么讀過(guò)此文你會(huì)清晰無(wú)比!首先談卜聲明與定義的區(qū)別。聲明是將一個(gè)名稱引入程序。定義提供了一個(gè)實(shí)體在程序中的唯一描述。聲明 和定義有時(shí)是同時(shí)存在的。如 int a;extern int b=1;只有當(dāng)extern中不存在初始化式是才是聲明。其他情況既是定義也是聲明。但是在下列情況下,聲明僅僅是聲明:1:僅僅提供函數(shù)原型。如void func(int,int);2: ext

2、ern int a;3: class a;4: typedef 聲明5:在類中定義的靜態(tài)數(shù)據(jù)成員的聲明如:cpp view plaincopy1. <span styontsize: 18px;n>class a2. 3. public:4. static int a;聲明。5. ;</span>cpp view plaincopy1 <span style=hfont-size:18px;n>class a2. 3. public:4. static int a;/聲明。5;</span>下列情況下,定義僅僅是定義:1:在類定義之外,定義并初始

3、化一個(gè)靜態(tài)數(shù)據(jù)成員。如a:a=0;2:在類外定義非內(nèi)聯(lián)成員函數(shù)。聲明僅僅是將一個(gè)符號(hào)引入到一個(gè)作用域。而定義提供了一個(gè)實(shí)體在程序中的唯 一描述。在一個(gè)給定的定義域屮重復(fù)聲明一個(gè)符號(hào)是可以的,但是卻不能重復(fù)定義, 否則將會(huì)引起編譯錯(cuò)誤。但是在類中的成員函數(shù)和靜態(tài)數(shù)據(jù)成員卻是例外,雖然在 類內(nèi)它們都是聲明,但是也不能有多個(gè)。如:cpp view plain copy1. <span style=hfont-size: 18px;n>class a2. 3. public:4statix int a;5static int a;6voidfunc(int,int);7. voidfunc

4、(int8. ;</span>cpp view plain copy1. <span style=hfont-size:18px;h>class a2. 3. public:4. static int a;5static int a;6. voidfunc(int7. voidfunc(intint);8;</span>明白了聲明與定義的區(qū)別,還需要明白內(nèi)部鏈接、外部鏈接。只有明白了它 們你才會(huì)知道開(kāi)頭提出的問(wèn)題。在編譯時(shí),編譯器只檢測(cè)程序語(yǔ)法和函數(shù)、變量是否被聲明。如果函數(shù)未被聲 明,編譯器會(huì)給出一個(gè)警告,但可以牛成冃標(biāo)文件。而在鏈接程序時(shí),鏈接器會(huì)在 所

5、有的訂標(biāo)文件屮找尋函數(shù)的實(shí)現(xiàn)。如果找不到,那到就會(huì)報(bào)鏈接錯(cuò)誤碼(linker error) o在vc下,這種錯(cuò)誤一般是:link 2001錯(cuò)誤,意思說(shuō)是說(shuō),鏈接器未能找 到函數(shù)的實(shí)現(xiàn)。鏈接把不同編譯單元產(chǎn)生的符號(hào)聯(lián)系起來(lái)。有兩種鏈接方式:內(nèi)部鏈接和外部 鏈接。如果一個(gè)符號(hào)名對(duì)于它的編譯單元來(lái)說(shuō)是局部的,并fl在鏈接時(shí)不可能與其他 編譯單元中的同樣的名稱相沖突,那個(gè)這個(gè)符號(hào)就是內(nèi)部鏈接。內(nèi)部鏈接意味著對(duì) 此符號(hào)的訪問(wèn)僅限于當(dāng)前的編譯單元屮,對(duì)其他編譯單元都是不可見(jiàn)的。static關(guān)鍵字作用在全局變量時(shí),表示靜態(tài)全局變量。但是作用域僅僅在當(dāng)前 文件作用域內(nèi)。其他文件中即使使用extern聲明也是無(wú)

6、法使用的。const也類似。帶冇static> const關(guān)鍵字和枚舉類型的連接是內(nèi)部的。具有內(nèi)部鏈接的符號(hào)無(wú)法作用于當(dāng)前文件外部,要讓其彩響程序的其他部分, 可以將其放在h文件中。此時(shí)在所有包含此.h文件的源文件都有自己的定義且互不 影響。類的定義具有內(nèi)部鏈接,由于它是定義,因此在同一編譯單元屮不能重復(fù)出現(xiàn)。 如果需要在其他編譯單元使用,類必須被定義在頭文件且被其他文件包含。僅僅在 其他文件屮使用class a;聲明是不行的,原因就是類的定義是內(nèi)部鏈接,不會(huì)在目標(biāo) 文件導(dǎo)出符號(hào)。也就不會(huì)被其他單元解析它們的未定義符號(hào)。理解這一點(diǎn)很重要。內(nèi)聯(lián)函數(shù)也具有內(nèi)部鏈接。在一個(gè)多文件的程序中,如果

7、一個(gè)符號(hào)在鏈接時(shí)可以和其他編譯單元交互,那 么這個(gè)名稱就有外部鏈接。外部鏈接意味著該定義不僅僅局限在單個(gè)編譯單元中。 它可以在o文件屮產(chǎn)生外部符號(hào)??梢员黄渌幾g單元訪問(wèn)用來(lái)解析它們未定義的 符號(hào)。因此它們?cè)谡麄€(gè)程序中必須是唯一的,否則將會(huì)導(dǎo)致重復(fù)定義。非內(nèi)聯(lián)成員函數(shù)、非內(nèi)聯(lián)函數(shù)、非靜態(tài)自由函數(shù)都具有外部鏈接。內(nèi)聯(lián)函數(shù)z所冇具冇內(nèi)部鏈接,因?yàn)榫幾g器在可能的時(shí)候,會(huì)將所冇對(duì)函數(shù) 的調(diào)用替換為函數(shù)體,不將任何符號(hào)寫入o文件。判斷-個(gè)符號(hào)是內(nèi)部鏈接還是外部鏈接的一個(gè)很好的方法就是看該符號(hào)是否 被寫入.0文件。前面說(shuō)的是定義對(duì)鏈接方式的影響,接下來(lái)說(shuō)下聲明對(duì)鏈接方式的影響。 由于聲明只對(duì)當(dāng)前編譯單元有

8、用,因此聲明并不將任何東西寫入.0文件。女口 extern int a;int func();這些聲明本身不會(huì)影響到.o文件的內(nèi)容。每一個(gè)都只是命名一個(gè)外部符號(hào),使 當(dāng)前的編譯單元在需要的時(shí)候可以訪問(wèn)相應(yīng)的全局定義。函數(shù)調(diào)用會(huì)導(dǎo)致一個(gè)未定義的符號(hào)被寫入到.0文件。如果a在該文件屮沒(méi)有被使 用,那么沒(méi)有被寫入到.o文件。而func函數(shù)有對(duì)此函數(shù)的調(diào)用。也就會(huì)將此符號(hào)寫 入h標(biāo)文件。此后此.0文件與定義此符號(hào)的.0文件被連接在一起,前面未定義的符 號(hào)被解析。上述聲明冇可能導(dǎo)致該符號(hào)被寫入冃標(biāo)文件中。但是以下聲明并不會(huì)導(dǎo)致該符號(hào) 寫入到冃標(biāo)文件中。如:cpp view plaincopy1 <

9、span style=mfont-size: 18px;">typedef int int; class a;2 struct s;3 union point;</span>cpp view plaincopy1. <span style= hfont-size:18px;m>typedef int int: class a;2. struct s;3 union point;</span>它們的鏈接也是內(nèi)部的。類聲明和類定義都是內(nèi)部鏈接。只是為當(dāng)前編譯單元所用。靜態(tài)的類數(shù)據(jù)成員的定義具有外部鏈接。如cpp view plaincopy1.

10、<span style=hfont-size: 18px;h>class a2. 3. static int a;/聲明。具有內(nèi)部鏈接。4: </span>pp view plaincopy1. <span style=mfsize:18px;h>class a2. 3. static int a;/聲明。具tt內(nèi)制鏈接。4: </span>靜態(tài)數(shù)據(jù)成員a僅僅是一個(gè)聲明,但是它的定義a:a=0;卻具有外部鏈接。c+對(duì)類和枚舉類型的處理方式是不一樣的。比如:在不定義類時(shí)可以聲明一個(gè) 類。但是不能未經(jīng)定義就聲明一個(gè)枚舉類型?;谝陨系姆治?,我們可以知

11、道:將具有外部鏈接的定義放在頭文件屮幾乎都是 編程錯(cuò)誤。因?yàn)槿绻擃^文件中被多個(gè)源文件包含,那么就會(huì)存在多個(gè)定義,鏈接 時(shí)就會(huì)出錯(cuò)。在頭文件中放置內(nèi)部鏈接的定義卻是合法的,但不推薦使用的。因?yàn)轭^文件被包 含到多個(gè)源文件中時(shí),不僅僅會(huì)污染全局命名空間,而且會(huì)在每個(gè)編譯單元中有自 己的實(shí)休存在。人量:消耗內(nèi)存空間,述會(huì)影響機(jī)器性能。const和static修飾的全局變量?jī)H僅在當(dāng)前文件作用域內(nèi)有效。它們具有內(nèi)部鏈 接屬性。下面列出一些應(yīng)該或是不應(yīng)該寫入頭文件的定義:cpp view plaincopy1. <span style=hfont-size: 18px;n>/test.h2.

12、#ifndef test_h3. #define test_h4. int a;/a有外部鏈接,不能在頭文件中定義。5. extern int b=10: 同上。6. const int c=2;/c具有內(nèi)部鏈接,可以定在頭文件中但應(yīng)該避免。7. static int d=3;/同上。8. static void func() 同上©9. void func2() 同 a。10. void func3();可以。僅僅是聲明。并不會(huì)導(dǎo)致符號(hào)名被寫入目標(biāo)文件。11. class a13.public:14. static int e;/nj以,具彳j內(nèi)部鏈接。15. int f; m以,

13、同上。16void func4();/聲明,內(nèi)部鏈接。同上。17. ;18. a:e=10;/不可以在頭文件中包含具有外部鏈接的定義。符號(hào)名別寫入ii標(biāo)文件。19. void a:func4()/不可以,類成員函數(shù)。夕卜部連接。2021. /,22. 23 #endif</span>cpp view plaincopy1. <span style=mfont-size:18px;m>/test.h2. #ifndef test_h3. #define test_h4. int a; /a有外部鏈接,不能在頭文件中定義。5 extern int b=10; /同上

14、9;6. const int c=2;/c具有內(nèi)部鏈接,可以定在頭文件中但應(yīng)該避免。7. static int d=3;/同上。8. static void func() /同上。9. void func2() /同 a。10. void func3();/«f以。僅僅是卅叨。并不會(huì)導(dǎo)致符號(hào)名被寫入h標(biāo)文件。class a12. 13. public:14. static int e;/可以,具有內(nèi)部鏈接。15int f; /可以,同上。16. void func4();/聲明,內(nèi)部鏈接。同上。17. ;18a:e“0;/不可以在頭文件中包含具有外部鏈接的定義。符號(hào)名別藥入ii標(biāo)文件

15、。19. void a:func4()/不町以,類成員函數(shù)。外部連接。2021 /,22. 23 tfendif</span>和信大家現(xiàn)在明口為什么只在類型聲明成員函數(shù),而不實(shí)現(xiàn)它是合法的了。也 可以回答為什么類的定義可以放在.h文件中。而類的實(shí)現(xiàn)可以放在同名的cpp文件 中。老師以前的介紹是說(shuō)編譯器會(huì)b動(dòng)尋找同名的cpp文件。其實(shí)是因?yàn)榍赾pp 文件屮存儲(chǔ)的是成員函數(shù)的實(shí)現(xiàn),而成員函數(shù)具有外部鏈接特性,會(huì)在目標(biāo)文件產(chǎn) 生符號(hào)。在此文件中此符號(hào)是定義過(guò)的。其他調(diào)用此成員函數(shù)的口標(biāo)文件也會(huì)產(chǎn)生 一個(gè)未定的符號(hào)。兩目標(biāo)文件連接后此符號(hào)就被解析。注意static數(shù)據(jù)成員應(yīng)該放在 cpp

16、文件屮。而不能放在.h文件。有內(nèi)部鏈接的定義可以定義在cpp文件中,并不會(huì)影響全丿的符號(hào)空間。但是 在cpp文件作用域屮要避免定義(并不禁止)沒(méi)有聲明為靜態(tài)的數(shù)據(jù)和函數(shù),因?yàn)?它們具有外部鏈接。如cpp view plaincopy1. <span style=hfont-size: 18px;"> int a;2. void func()3. 4. 5. </span>cpp view plain copy1. <span style=mfont-size:18px;int a;2. void func()3. 4. 5. </span>上

17、述定義具有外部鏈接可能會(huì)與全局命名空間的其他符號(hào)名稱存在潛在沖突。 如果確實(shí)需要使用全局的變量或函數(shù)。可以為它們加上static關(guān)鍵字。使其作用域 局限在當(dāng)前文件內(nèi),具有內(nèi)部鏈接也就不會(huì)對(duì)全局命名空間產(chǎn)生影響。因?yàn)閮?nèi)聯(lián)函 數(shù)和靜態(tài)自由函數(shù)、枚舉以& const類型的數(shù)據(jù)都具冇內(nèi)部鏈接,所以它們可以定義 在cpp文件屮,而不會(huì)影響全局命名空間。typedef和宏定義不會(huì)將符號(hào)引入.o文件,它們也可以出現(xiàn)在cpp文件屮,不會(huì) 影響全局命名空間。typedef為一個(gè)已存在的類型創(chuàng)建一個(gè)別名。而不是創(chuàng)建一個(gè)新的類型。它不提 供類型安全。如cpp view plain copy1 <span style=hfont-size: 18px;n>typedef int inta:2. typedef int inb: </span>cpp view plain copy1. <span style=mfont-size:18px;h>typedef int inta;2 typedef int inb; </span>在需

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論