C++頭文件規(guī)則介紹
C++中的C++頭文件是用戶應(yīng)用程序和函數(shù)庫(kù)之間的橋梁和紐帶,在整個(gè)軟件中,頭文件不是最重要的部分,但它是C++語(yǔ)言家族中不可缺少的組成部分,有了它給技術(shù)人員提供了大大的便捷。
因?yàn)橐粋€(gè)頭文件的內(nèi)容實(shí)際上是會(huì)被引 入到多個(gè)不同的.cpp文件中的,并且它們都會(huì)被編譯。放聲明當(dāng)然沒事,如果放了定義,那么也就相當(dāng)于在多個(gè)文件中出現(xiàn)了對(duì)于一個(gè)符號(hào)(變量或函數(shù))的定 義,縱然這些定義都是相同的,但對(duì)于編譯器來(lái)說,這樣做不合法。
所以,應(yīng)該記住的一點(diǎn)就是,.h頭文件中,只能存在變量或者函數(shù)的聲明, 而不要放定義。即,只能在C++頭文件中寫形如:extern int a;和void f();的句子。這些才是聲明。如果寫上int a;或者void f() {}這樣的句子,那么一旦這個(gè)頭文件被兩個(gè)或兩個(gè)以上的.cpp文件包含的話,編譯器會(huì)立馬報(bào)錯(cuò)。(關(guān)于extern,前面有討論過,這里不再討論定義跟 聲明的區(qū)別了。)
但是,這個(gè)規(guī)則是有三個(gè)例外的。
一,頭文件中可以寫const對(duì)象的定義。因?yàn)槿值腸onst對(duì)象默 認(rèn)是沒有extern的聲明的,所以它只在當(dāng)前文件中有效。把這樣的對(duì)象寫進(jìn)頭文件中,即使它被包含到其他多個(gè).cpp文件中,這個(gè)對(duì)象也都只在包含它的 那個(gè)文件中有效,對(duì)其他文件來(lái)說是不可見的,所以便不會(huì)導(dǎo)致多重定義。同時(shí),因?yàn)檫@些.cpp文件中的該對(duì)象都是從一個(gè)頭文件中包含進(jìn)去的,這樣也就保證 了這些.cpp文件中的這個(gè)const對(duì)象的值是相同的,可謂一舉兩得。同理,static對(duì)象的定義也可以放進(jìn)C++頭文件。
二,C++頭文件中可 以寫內(nèi)聯(lián)函數(shù)(inline)的定義。因?yàn)閕nline函數(shù)是需要編譯器在遇到它的地方根據(jù)它的定義把它內(nèi)聯(lián)展開的,而并非是普通函數(shù)那樣可以先聲明再鏈 接的(內(nèi)聯(lián)函數(shù)不會(huì)鏈接),所以編譯器就需要在編譯時(shí)看到內(nèi)聯(lián)函數(shù)的完整定義才行。
如果內(nèi)聯(lián)函數(shù)像普通函數(shù)一樣只能定義一次的話,這事兒就難辦了。因?yàn)樵?一個(gè)文件中還好,我可以把內(nèi)聯(lián)函數(shù)的定義寫在最開始,這樣可以保證后面使用的時(shí)候都可以見到定義;但是,如果我在其他的文件中還使用到了這個(gè)函數(shù)那怎么辦呢?
這幾乎沒什么太好的解決辦法,因此C++規(guī)定,內(nèi)聯(lián)函數(shù)可以在程序中定義多次,只要內(nèi)聯(lián)函數(shù)在一個(gè).cpp文件中只出現(xiàn)一次,并且在所有的.cpp文 件中,這個(gè)內(nèi)聯(lián)函數(shù)的定義是一樣的,就能通過編譯。那么顯然,把內(nèi)聯(lián)函數(shù)的定義放進(jìn)一個(gè)頭文件中是非常明智的做法。
三,頭文件中可以寫類 (class)的定義。因?yàn)樵诔绦蛑袆?chuàng)建一個(gè)類的對(duì)象時(shí),編譯器只有在這個(gè)類的定義完全可見的情況下,才能知道這個(gè)類的對(duì)象應(yīng)該如何布局,所以,關(guān)于類的 定義的要求,跟內(nèi)聯(lián)函數(shù)是基本一樣的。
所以把類的定義放進(jìn)C++頭文件,在使用到這個(gè)類的.cpp文件中去包含這個(gè)C++頭文件,是一個(gè)很好的做法。在這里,值得一提 的是,類的定義中包含著數(shù)據(jù)成員和函數(shù)成員。
數(shù)據(jù)成員是要等到具體的對(duì)象被創(chuàng)建時(shí)才會(huì)被定義(分配空間),但函數(shù)成員卻是需要在一開始就被定義的,這也就 是我們通常所說的類的實(shí)現(xiàn)。一般,我們的做法是,把類的定義放在頭文件中,而把函數(shù)成員的實(shí)現(xiàn)代碼放在一個(gè).cpp文件中。這是可以的,也是很好的辦法。
不過,還有另一種辦法。那就是直接把函數(shù)成員的實(shí)現(xiàn)代碼也寫進(jìn)類定義里面。在C++的類中,如果函數(shù)成員在類的定義體中被定義,那么編譯器會(huì)視這個(gè)函數(shù)為 內(nèi)聯(lián)的。因此,把函數(shù)成員的定義寫進(jìn)類定義體,一起放進(jìn)頭文件中,是合法的。
注意一下,如果把函數(shù)成員的定義寫在類定義的C++頭文件中,而沒有寫進(jìn)類定義中, 這是不合法的,因?yàn)檫@個(gè)函數(shù)成員此時(shí)就不是內(nèi)聯(lián)的了。一旦頭文件被兩個(gè)或兩個(gè)以上的.cpp文件包含,這個(gè)函數(shù)成員就被重定義了。
【編輯推薦】