由多個(gè)文件組成的程序需要一種方法連接名字的使用和聲明,在C++中是通過頭文件實(shí)現(xiàn)的。頭文件一般包括類的定義,extern 變量的聲明和函數(shù)的聲明。使用或定義這些實(shí)體的文件要包含適當(dāng)?shù)念^文件。 頭文件的正確使用有兩個(gè)好處:保證所有文件使用給定實(shí)體的同一聲明;當(dāng)聲明需要修改時(shí),只有頭文件需要更新。在定義頭文件時(shí)要注意頭文件中所做的聲明在邏輯上應(yīng)該是適于放在一起的,否則,編譯頭文件會花費(fèi)較長時(shí)間。 使用頭文件時(shí)需要注意以下幾點(diǎn):
當(dāng)定義頭文件時(shí),記住定義和聲明的區(qū)別是很重要的。定義只可以出現(xiàn)一次,而聲明可以出現(xiàn)多次。因?yàn)轭^文件包含在多個(gè)源文件中,所以不應(yīng)該含有變量或函數(shù)的定義,否則會造成在同一個(gè)程序?qū)ν粋€(gè)變量或函數(shù)的多次定義。下列語句是定義,所以不應(yīng)該放在頭文件中: extern int ival = 10; double ix; 對頭文件不應(yīng)該含有定義這一規(guī)則,有三個(gè)例外。頭文件可以定義類,值在編譯時(shí)就已經(jīng)知道的const對象和inline函數(shù)。這些實(shí)體可以在多個(gè)源文件中定義,只要每個(gè)源文件中的定義是相同的。 在頭文件中定義這些實(shí)體,是因?yàn)榫幾g器需要它們的定義來產(chǎn)生代碼。例如:為了產(chǎn)生能定義或使用類的對象的代碼,編譯器需要知道組成該類型的數(shù)據(jù)成員,同樣還需要知道能夠在這些對象上執(zhí)行的操作。對于const對象,作以下說明: 除非特別說明,在全局作用域聲明的const變量默認(rèn)為是定義該對象的文件的局部變量。此變量只存在于那個(gè)文件中,不能被其他文件訪問。通過指定const變量為extern,就可以在整個(gè)程序中訪問const對象。例如: //在file1中定義變量ix extern const int ix = 5; //在file2中我們可以這樣使用它 extern const int ix; for (int index = 0; index != ix; ++index) {…} 通過對const變量進(jìn)行為編譯器可見的初始化式初始化后,const變量成為常量表達(dá)式。為了能夠讓const變量和它的初始化式在每個(gè)文件中都可見,一般都把這樣的const變量定義在頭文件中,從而使包含該頭文件的文件都可以使用相同的常量值。無論該const變量何時(shí)使用,編譯器都可以看見其初始化式。在C++中任何變量都只能定義一次,定義會分配存儲空間,而所有對該變量的使用都關(guān)聯(lián)到同一存儲空間,因?yàn)閏onst對象默認(rèn)為定義它的文件的局部變量,所以把它們定義放在頭文件中是合法的。 如果const變量不是用常量表達(dá)式初始化,那么它就不應(yīng)該在頭文件中定義,相反,它應(yīng)該和其他變量一樣,該const變量應(yīng)該在一個(gè)源文件中定義并初始化,然后在頭文件中為它添加extern聲明,以使其能被多個(gè)文件共享。
#include設(shè)施是C++預(yù)處理器的一部分,它只接受一個(gè)參數(shù):頭文件名。預(yù)處理器用指定的頭文件的內(nèi)容替代每個(gè)#include.
頭文件經(jīng)常#include其他頭文件,頭文件定義的實(shí)體經(jīng)常使用其他頭文件的設(shè)施,在同一源文件中還可能多次包含同一頭文件。比如我們自己定義了一個(gè)Query.h的頭文件,該頭文件中包含了string的頭文件。同時(shí),我們在編寫源代碼時(shí)也使用了string庫,這樣string 庫就包含了兩次:一次是通過程序本身直接包含,一次是通過包含Query頭文件間接包含。 設(shè)計(jì)頭文件時(shí),應(yīng)使其可以多次包含在同一源文件中,我們必須保證多次包含同一頭文件不會引起該頭文件中定義的類和對象被多次定義,使得頭文件安全的通用做法,是使用預(yù)處理器定義頭文件保護(hù)符來避免在已經(jīng)見到頭文件的情況下重新處理該頭文件的內(nèi)容。
為了避免名字沖突,預(yù)處理變量經(jīng)常用全大寫字母表示。預(yù)處理變量有兩種狀態(tài):已定義或未定義。定義預(yù)處理器變量和檢測其狀態(tài)所用的預(yù)處理指示不同。#define指示接受一個(gè)名字并定義該名字為預(yù)處理變量。#ifndef指示檢測指定的預(yù)處理器變量是否未定義。如果預(yù)處理器變量未定義,那么跟在其后的所有指示都被處理,直到出現(xiàn)#endif。可以使用這種方法來預(yù)防多次包含同一頭文件。 #ifndef QUERY_H #define QUERY_H //定義query.h中的內(nèi)容 #endif
條件指示 #ifndef QUERY_H 測試 QUERY_H預(yù)處理器變量是否未定義。如果 QUERY_H未定義,那么#ifndef測試成功,跟在#ifndef后面的所有行都被執(zhí)行,直到發(fā)現(xiàn)#endif.相反,如果QUERY_H已定義,那么#infdef指示測試為假,該指示和#endif指示之間的代碼都被忽略。通常情況下,我們用定義在頭文件中的實(shí)體(如類)來命名預(yù)處理器變量來避免預(yù)處理器變量重名的問題。通過使用類名來組成頭文件和預(yù)處理器變量的名字,可以使得很可能只有一個(gè)文件將會使用該預(yù)處理器變量。
#include指示接受以下兩種形式: #include<iostream> #include"query.h" 如果頭文件名括在尖括號< >里,那么認(rèn)為該頭文件是標(biāo)準(zhǔn)頭文件。編譯器會在預(yù)定義的位置集查找該頭文件,這些預(yù)定義的位置可以通過設(shè)置查找路徑環(huán)境變量或者通過命令行選項(xiàng)來修改。如果頭文件名括在一對引號里,那么認(rèn)為它是非系統(tǒng)頭文件,非系統(tǒng)頭文件的查找通常開始于源文件所在的路徑。
新聞熱點(diǎn)
疑難解答
圖片精選