c++ *.h和*.cpp在编译中的作用
首先,我們可以將所有東西都放在一個(gè).cpp文件內(nèi).然后編譯器就將這個(gè).cpp編譯成.obj,obj是什么東西?就是編譯單元了.
一個(gè)程序,可以由一個(gè)編譯單元組成,也可以有多個(gè)編譯單元組成.?如果你不想讓你的源代碼變得很難閱讀的話,就請(qǐng)使用多個(gè)編譯單元吧.(一個(gè)函數(shù)不能放到兩個(gè)編譯單元里面,但兩個(gè)以上就可以分別放在一個(gè)單元,也就是cpp里面)那么就是一個(gè).cpp對(duì)應(yīng)一個(gè).obj,然后將所有的obj鏈接起來(lái)(通過(guò)一個(gè)叫鏈接器的程序),組成一個(gè).exe,也就是程序了.
如果一個(gè).cpp要用到另一個(gè).cpp定義的函數(shù)怎么辦??只需在這個(gè).cpp種寫(xiě)上他的函數(shù)聲明就可以了.其余工作由鏈接器幫你完成,你可以隨便調(diào)用該函數(shù).鏈接器將所有的obj連接起來(lái),但是如果碰巧有相同的函數(shù)或外部變量怎么辦?他如何識(shí)別?一般來(lái)說(shuō)是不能允許在同一個(gè)程序中,出現(xiàn)兩個(gè)一樣的函數(shù)名或外部變量名.但是只得慶幸的是,c++可以通過(guò)一種叫做鏈接屬性的關(guān)鍵字來(lái)限定,你這個(gè)函數(shù)是屬于整個(gè)程序公用的,還是只是在一個(gè)編譯單元obj里面使用的.這些關(guān)鍵字就是extern?和?static;?extern是外部鏈接的意思,也就是除了這個(gè)單元,外部的單元也是能夠訪問(wèn)這個(gè)函數(shù)的.static?是內(nèi)部鏈接,自屬于自己?jiǎn)卧?span lang="en-us">.說(shuō)了這么久,還沒(méi)有說(shuō).h的作用呢?其實(shí)沒(méi)有.h也能很好的工作,但是當(dāng)你發(fā)現(xiàn)一個(gè)外部鏈接的函數(shù)或外部變量,需要許多份聲明,因?yàn)?span lang="en-us">c++這種語(yǔ)言,在使用函數(shù)和變量的時(shí)候,必須將他聲明,為何要聲明?聲明之后才知道他的規(guī)格,才能更好的發(fā)現(xiàn)不和規(guī)格的部分.你別妄想一個(gè)編譯單元,會(huì)自動(dòng)從另一個(gè)編譯單元那里得到什么信息,知道你是如何定義這個(gè)函數(shù)的.所以說(shuō),只要使用到該函數(shù)的單元,就必須寫(xiě)一份聲明在那個(gè).cpp里面,這樣是不是很麻煩,而且,如果要修改,就必須一個(gè)一個(gè)修改.這真讓人受不了..h就是為了解決這個(gè)問(wèn)題而誕生,他包含了這些公共的東西.然后所有需要使用該函數(shù)的.cpp,只需要用#include包含進(jìn)去便可.以后需要修改,也只是修改一份內(nèi)容.請(qǐng)注意不要濫用.h,.h里面不要寫(xiě)代碼,.h不是.cpp的倉(cāng)庫(kù),什么都塞到里面.如果在里面寫(xiě)代碼,當(dāng)其他.cpp包含他的時(shí)候,就會(huì)出現(xiàn)重復(fù)定義的情況,比如將函數(shù)func(){printf};放到頭文件a.h,里面還有一些a.cpp需要的聲明等;然后你發(fā)現(xiàn)b.cpp需要用到a.cpp里面的一個(gè)函數(shù),就很高興的將a.h包含進(jìn)來(lái).注意,#include并不是什么申請(qǐng)指令,他就是將指定的文件的內(nèi)容,原封不動(dòng)的拷貝進(jìn)來(lái).這時(shí)候?qū)嶋H上a.cpp和b.cpp都有一個(gè)func()函數(shù)的定義.如果這個(gè)函數(shù)是內(nèi)部鏈接static的話,還好,浪費(fèi)了一倍空間;如果是extern,外部鏈接(這個(gè)是默認(rèn)情況),那么根據(jù)在同一個(gè)程序內(nèi)不可出現(xiàn)同名函數(shù)的要求,連接器會(huì)毫不留情給你一個(gè)連接錯(cuò)誤!;如果你還不太理解.那么就嘗試不用h,只用多個(gè)cpp看看應(yīng)該如何寫(xiě).嘗試在兩個(gè)cpp中寫(xiě)同名函數(shù).看看是否鏈接出錯(cuò).嘗試在cpp使用其他cpp定義的函數(shù).看看應(yīng)該如何做.
頭文件是沒(méi)有編譯意義的,一般只是編譯.cpp生成.obj.但是.cpp里面有#include將指定頭文件(其實(shí)任何文件都行)插進(jìn)來(lái),組成完整的.cpp.如果你不喜歡這個(gè)方式,你也可以直接在.cpp里面寫(xiě)好了,而不放到.h里面,載用指令拷貝進(jìn)來(lái).頭文件是工具,但不是必須.
個(gè)人認(rèn)為:
???? .cpp內(nèi)用于(1)函數(shù)實(shí)現(xiàn)(包括全局函數(shù)(默認(rèn))、靜態(tài)函數(shù))。
???????????????(2)全局變量、靜態(tài)變量定義。
???????????????(3)靜態(tài)函數(shù)聲明,靜態(tài)變量聲明。(指定編譯單元內(nèi)部使用的函數(shù)和變量)
?????.h內(nèi)用于??(1)全局函數(shù)聲明,注意靜態(tài)函數(shù)不包括在內(nèi)。
???????????????(2)全局變量聲明,無(wú)靜態(tài)變量。
--------------------------------------------------------------------------------------------------------------
我的一點(diǎn)總結(jié)?by ordedere
上文說(shuō)到,#include并不是什么申請(qǐng)指令,他就是將指定的文件的內(nèi)容,原封不動(dòng)的拷貝進(jìn)來(lái)。所以我們可以將.h的代碼連接到.cpp的前端,從而可以更加清晰的看到:
a.h, b.cpp & c.cpp 都同時(shí)include了a.h,那么b.cpp其實(shí)可以看做是文件:a.h+b.cpp連接而成的cpp源碼;而a.h+c.cpp連接成的源碼等價(jià)于c.cpp include a.h。
那么對(duì)于變量在.h中的聲明,對(duì)cpp有如下情況的分類(lèi):
在.h中聲明變量int a,等價(jià)于在.cpp的前端聲明(或者定義)變量全局變量int a;
在.h中聲明外部變量extern int a; 等價(jià)于在.cpp 的前端聲明了外部變量a;所以這個(gè)變量a被指明在其他cpp文件中定義;
在.h中聲明全局變量 static int a; 等價(jià)于在所有包含.h的cpp中將有文件內(nèi)部的變量a,且每個(gè)include該h文件的cpp中的a變量的地址是不同的,也就是原作者說(shuō)道的空間浪費(fèi)問(wèn)題。
同理,對(duì)于函數(shù)的聲明:
在.h 中聲明靜態(tài)(static)函數(shù),就相當(dāng)于在所包含該頭文件的cpp程序中需要定義該靜態(tài)函數(shù);
在.h中聲明外部(extern)函數(shù),即指明該函數(shù)的定義是在其他源文件中。
在.h中聲明普通函數(shù),即在cpp的開(kāi)始部分聲明一個(gè)函數(shù)是一個(gè)道理。
?
所以:靜態(tài)函數(shù)和全局靜態(tài)變量的聲明應(yīng)該在cpp中(畢竟靜態(tài)的意義就是確保該函數(shù)或者變量的作用空間僅限于該源文件內(nèi)部),而避免在.h中有靜態(tài)變量或函數(shù)的聲明。
總結(jié)
以上是生活随笔為你收集整理的c++ *.h和*.cpp在编译中的作用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SpringMVC 学习系列 (4) 之
- 下一篇: C++ TypeId简介与使用