C++中聲明與定義的區(qū)別_第1頁
C++中聲明與定義的區(qū)別_第2頁
C++中聲明與定義的區(qū)別_第3頁
C++中聲明與定義的區(qū)別_第4頁
C++中聲明與定義的區(qū)別_第5頁
已閱讀5頁,還剩2頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

C++學(xué)了這么多年你知道為什么定義類時,類的定義放在.h文件中,而類的實現(xiàn)放在cpp文件中。它們?yōu)槭裁茨軌蜿P(guān)聯(lián)到一起呢?你知道什么東西可以放在.h文件中,什么不能。什么東西又可以放在cpp文件中。如果你忘記了或是壓根就不明白,那么讀過此文你會清晰無比?。∈紫日勏侣暶髋c定義的區(qū)別。聲明是將一個名稱引入程序。定義提供了一個實體在程序中的唯一描述。聲明和定義有時是同時存在的。如inta;externintb=1;只有當extern中不存在初始化式是才是聲明。其他情況既是定義也是聲明。但是在下列情況下,聲明僅僅是聲明:1:僅僅提供函數(shù)原型。如voidfunc(int,int);2:externinta;3:classA;4:typedef聲明5:在類中定義的靜態(tài)數(shù)據(jù)成員的聲明如:[cpp]viewplaincopy<spanstyle="font-size:18px;">classA12.{3.public:4.staticinta;//聲明。5.};</span>[cpp]viewplaincopy<spanstyle="font-size:18px;">classA12.{3.public:4.staticinta;//聲明。5.};</span>下列情況下,定義僅僅是定義:1:在類定義之外,定義并初始化一個靜態(tài)數(shù)據(jù)成員。如A::a=0;2:在類外定義非內(nèi)聯(lián)成員函數(shù)。聲明僅僅是將一個符號引入到一個作用域。而定義提供了一個實體在程序中的唯一描述。在一個給定的定義域中重復(fù)聲明一個符號是可以的,但是卻不能重復(fù)定義,否則將會引起編譯錯誤。但是在類中的成員函數(shù)和靜態(tài)數(shù)據(jù)成員卻是例外,雖然在類內(nèi)它們都是聲明,但是也不能有多個。如:[cpp]viewplaincopy<spanstyle="font-size:18px;">classA12.{3.public:4.staticinta;5.staticinta;6.voidfunc(int,int);7.voidfunc(int,int);};</span>[cpp]viewplaincopy<spanstyle="font-size:18px;">classA{3.public:4.staticinta;5.staticinta;6.voidfunc(int,int);7.voidfunc(int,int);};</span>明白了聲明與定義的區(qū)別,還需要明白內(nèi)部鏈接、外部鏈接。只有明白了它們你才會知道開頭提出的問題。在編譯時,編譯器只檢測程序語法和函數(shù)、變量是否被聲明。如果函數(shù)未被聲明,編譯器會給出一個警告,但可以生成目標文件。而在鏈接程序時,鏈接器會在所有的目標文件中找尋函數(shù)的實現(xiàn)。如果找不到,那到就會報鏈接錯誤碼(LinkerError)。在VC下,這種錯誤一般是:Link2001錯誤,意思說是說,鏈接器未能找到函數(shù)的實現(xiàn)。鏈接把不同編譯單元產(chǎn)生的符號聯(lián)系起來。有兩種鏈接方式:內(nèi)部鏈接和外部鏈接。如果一個符號名對于它的編譯單元來說是局部的,并且在鏈接時不可能與其他編譯單元中的同樣的名稱相沖突,那個這個符號就是內(nèi)部鏈接。內(nèi)部鏈接意味著對此符號的訪問僅限于當前的編譯單元中,對其他編譯單元都是不可見的。static關(guān)鍵字作用在全局變量時,表示靜態(tài)全局變量。但是作用域僅僅在當前文件作用域內(nèi)。其他文件中即使使用extern聲明也是無法使用的。const也類似。帶有static>const關(guān)鍵字和枚舉類型的連接是內(nèi)部的。具有內(nèi)部鏈接的符號無法作用于當前文件外部,要讓其影響程序的其他部分,可以將其放在.h文件中。此時在所有包含此.h文件的源文件都有自己的定義且互不影響。類的定義具有內(nèi)部鏈接,由于它是定義,因此在同一編譯單元中不能重復(fù)出現(xiàn)。如果需要在其他編譯單元使用,類必須被定義在頭文件且被其他文件包含。僅僅在其他文件中使用classa;聲明是不行的,原因就是類的定義是內(nèi)部鏈接,不會在目標文件導(dǎo)出符號。也就不會被其他單元解析它們的未定義符號。理解這一點很重要。內(nèi)聯(lián)函數(shù)也具有內(nèi)部鏈接。在一個多文件的程序中,如果一個符號在鏈接時可以和其他編譯單元交互,那么這個名稱就有外部鏈接。外部鏈接意味著該定義不僅僅局限在單個編譯單元中。它可以在.。文件中產(chǎn)生外部符號??梢员黄渌幾g單元訪問用來解析它們未定義的符號。因此它們在整個程序中必須是唯一的,否則將會導(dǎo)致重復(fù)定義。非內(nèi)聯(lián)成員函數(shù)、非內(nèi)聯(lián)函數(shù)、非靜態(tài)自由函數(shù)都具有外部鏈接。內(nèi)聯(lián)函數(shù)之所有具有內(nèi)部鏈接,因為編譯器在可能的時候,會將所有對函數(shù)的調(diào)用替換為函數(shù)體,不將任何符號寫入.。文件。判斷一個符號是內(nèi)部鏈接還是外部鏈接的一個很好的方法就是看該符號是否被寫入?。文件。前面說的是定義對鏈接方式的影響,接下來說下聲明對鏈接方式的影響。由于聲明只對當前編譯單元有用,因此聲明并不將任何東西寫入?。文件。如externinta;intfunc();這些聲明本身不會影響到.。文件的內(nèi)容。每一個都只是命名一個外部符號,使當前的編譯單元在需要的時候可以訪問相應(yīng)的全局定義。函數(shù)調(diào)用會導(dǎo)致一個未定義的符號被寫入到?。文件。如果a在該文件中沒有被使用,那么沒有被寫入到?。文件。而func函數(shù)有對此函數(shù)的調(diào)用。也就會將此符號寫入目標文件。此后此?。文件與定義此符號的.。文件被連接在一起,前面未定義的符號被解析。上述聲明有可能導(dǎo)致該符號被寫入目標文件中。但是以下聲明并不會導(dǎo)致該符號寫入到目標文件中。如:[cpp]viewplaincopy<spanstyle="font-size:18px;">typedefintInt;ClassA;structs;unionpoint;</span>[cpp]viewplaincopy<spanstyle="font-size:18px;">typedefintInt;ClassA;structs;unionpoint;</span>它們的鏈接也是內(nèi)部的。類聲明和類定義都是內(nèi)部鏈接。只是為當前編譯單元所用。

靜態(tài)的類數(shù)據(jù)成員的定義具有外部鏈接。如[cpp]viewplaincopy<spanstyle="font-size:18px;">classA(staticinta;//聲明。具有內(nèi)部鏈接。};</span>[cpp]viewplaincopy<spanstyle="font-size:18px;">classA(staticinta;//聲明。具有內(nèi)部鏈接。};</span>靜態(tài)數(shù)據(jù)成員a僅僅是一個聲明,但是它的定義A::a=0;卻具有外部鏈接。C++對類和枚舉類型的處理方式是不一樣的。比如:在不定義類時可以聲明一個類。但是不能未經(jīng)定義就聲明一個枚舉類型?;谝陨系姆治?,我們可以知道:將具有外部鏈接的定義放在頭文件中幾乎都是編程錯誤。因為如果該頭文件中被多個源文件包含,那么就會存在多個定義,鏈接時就會出錯。在頭文件中放置內(nèi)部鏈接的定義卻是合法的,但不推薦使用的。因為頭文件被包含到多個源文件中時,不僅僅會污染全局命名空間,而且會在每個編譯單元中有自己的實體存在。大量消耗內(nèi)存空間,還會影響機器性能。const和static修飾的全局變量僅僅在當前文件作用域內(nèi)有效。它們具有內(nèi)部鏈接屬性。下面列出一些應(yīng)該或是不應(yīng)該寫入頭文件的定義:[cpp]viewplaincopy<spanstyle="font-size:18px;">//test.h#ifndefTEST_H#defineTEST_Hinta;//a有外部鏈接,不能在頭文件中定義。externintb=10;〃同上。constintc=2;//c具有內(nèi)部鏈接,可以定在頭文件中但應(yīng)該避免。staticintd=3;//同上。staticvoidfunc()(}〃同上。voidfunc2(){}〃同a。voidfunc3();//可以。僅僅是聲明。并不會導(dǎo)致符號名被寫入目標文件。classA{

public:staticinte;//可以,具有內(nèi)部鏈接。intf;〃可以,同上。voidfunc4();//聲明,內(nèi)部鏈接。同上。TOC\o"1-5"\h\z};A::e=10;//不可以在頭文件中包含具有外部鏈接的定義。符號名別寫入目標文件。voidA:func4()//不可以,類成員函數(shù)。外部連接。{//,}#endif</span>[cpp]viewplaincopy<spanstyle="font-size:18px;">//test.h#ifndefTEST_H#defineTEST_Hinta;//a有外部鏈接,不能在頭文件中定義。externintb=10;〃同上。constintc=2;//c具有內(nèi)部鏈接,可以定在頭文件中但應(yīng)該避免。staticintd=3;//同上。staticvoidfunc(){}〃同上。voidfunc2(){}〃同a。voidfunc3();//可以。僅僅是聲明。并不會導(dǎo)致符號名被寫入目標文件。classA{public:staticinte;//可以,具有內(nèi)部鏈接。intf;〃可以,同上。voidfunc4();//聲明,內(nèi)部鏈接。同上。TOC\o"1-5"\h\z};A::e=10;//不可以在頭文件中包含具有外部鏈接的定義。符號名別寫入目標文件。voidA:func4()//不可以,類成員函數(shù)。外部連接。{//,}#endif</span>相信大家現(xiàn)在明白為什么只在類型聲明成員函數(shù),而不實現(xiàn)它是合法的了。也可以回答為什么類的定義可以放在.h文件中。而類的實現(xiàn)可以放在同名的cpp文件中。老師以前的介紹是說編譯器會自動尋找同名的cpp文件。其實是因為由于cpp文件中存儲的是成員函數(shù)的實現(xiàn),而成員函數(shù)具有外部鏈接特性,會在目標文件產(chǎn)生符號。在此文件中此符號是定義過的。其他調(diào)用此成員函數(shù)的目標文件也會產(chǎn)生一個未定的符號。兩目標文件連接后此符號就被解析。注意static數(shù)據(jù)成員應(yīng)該放在cpp文件中。而不能放在.h文件。有內(nèi)部鏈接的定義可以定義在cpp文件中,并不會影響全局的符號空間。但是在cpp文件作用域中要避免定義(并不禁止)沒有聲明為靜態(tài)的數(shù)據(jù)和函數(shù),因為它們具有外部鏈接。如[cpp]viewplaincopy1.<spanstyle="font-size:18px;">inta;12.voidfunc()(}</span>[cpp]viewplaincopy1.<spanstyle="font-size:18px;">inta;12.voidfunc()(}</span>上述定義具有外部鏈接可能會與全局命名空間的其他符號名稱存在潛在沖突。如果確實需要使用全局的變量或函數(shù)。可以為它們加上static關(guān)鍵字。使其作用域局限在當前文件內(nèi),具有內(nèi)部鏈接也就不會對全局命名空間產(chǎn)生影響。因為內(nèi)聯(lián)函數(shù)和靜態(tài)自由函數(shù)、枚舉以及const類型的數(shù)據(jù)都具有內(nèi)部鏈接,所以它們可以定義在cpp文件中,而不會影響全局命名空間。typedef和宏定義不會將符號引入.。文件,它們也可以出現(xiàn)在cpp文件中,不會影響全局命名空間。typedef為一個已存在的類型創(chuàng)建一個別名。而不是創(chuàng)建一個新的類型。它不提供類型安全。如[cpp]viewplaincopy<spanstyle="font-size:18px;">typedefintIntA;typedefintInB;</span>[cpp]viewplaincopy<spanstyle="font-size:18px;">typedefintIntA;typedefintInB;</span>在需要IntA的地方使用IntB是不會報錯

溫馨提示

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

最新文檔

評論

0/150

提交評論