在閱讀頭文件時經常會看到一些 class QFile 等這類看似是聲明的東西.在命名空間中.例如下面
#ifndef WINDOW_H #define WINDOW_H QT_BEGIN_NAMESPACE class QTcpServer; class QTcpSocket; class QProgressBar; class QLabel; class QDialogButtonBox; class QFile; QT_END_NAMESPACE //code end class QAction; class QCheckBox; ...
如果刪除掉 將會 出現編譯的錯誤,對應變量未定義
那麼 這個是做什麼用的呢????
是因為在頭文件裡面只有這些類的指針申明,並沒有真正實例化,在使用這個類的頭文件對應的cpp文件裡面應該會包含定義這些類的頭文件
#include < QDialogButtonBox > #include < QFile > ...
在cpp文件裡面才會正真實例化這些類。
其實直接在頭文件裡面#include < QDialogButtonBox> #include< QFile>也是可以的,像它這樣做,好像是可以降低各個文件編譯時的關聯度,不會在改動了一下部分類的時候,引發其他大量文件的重新編譯,在做小工程的時候沒什麼區別,但是做大了,編譯一次需要好幾個小時的時候,這樣做的優勢就顯現出來了
class類名只是聲明存在這麼一個類,但是通過這個聲明無法得到任何關於此類的具體信息。這樣你可以在頭文件中其他使用到的地方聲明一個該類型的指針。
include頭文件則是將整個該頭文件與使用到的地方關聯起來。
使用class類名一般是為了去除編譯依賴,減少編譯消耗的時間
#include “xx.h” 在編譯的時候把xx.h文件直接展開,所以裡面的接口都能用,可以申明對象。但是class xx;這種方式就不會,你只能使用它的指針或者引用,你不能創建申明對象。
#define x //定義一個宏 ... #endif
//C語言在對程序進行編譯時,會先根據預處理命令進行“預處理”。C語言編譯系統包括預處理,編譯和鏈接等部分。
#ifndef x//先測試x是否被宏定義過 #define x 程序段1 //如果x沒有被宏定義過,定義x,並編譯程序段 1 #else 程序段2 //如果x已經定義過了則編譯程序段2的語句,“忽視”程序段 1。 #endif//終止if
條件指示符#ifndef 的最主要目的是防止頭文件的重復包含和編譯。了解:條件編譯當然也可以用條件語句來實現。 但是用條件語句將會對整個源程序進行編譯,生成的目標代碼程序很長,而采用條件編譯,則根據條件只編譯其中的程序段1或程序段2,生成的目標程序較短。如果條件選擇的程序段很長,采用條件編譯的方法是十分必要的。
#ifndef 標識1 //判斷”標識1”是否定義,如果被定義則返回假,如果沒有被定義則返回真。
/**********************************/ 語句1 #ifndef 標識1 語句2 #define 標識1 語句3 #endif 語句4 …… 語句5 …… 該段代碼意思是:如果標識1沒有被定義,則重定義標識1,即執行語句2、語句3;如果標識1已經被定義,則直接跳過語句2、語句3,直接執行語句4、語句5、…… /***********************************/
備注:#ifndef 和 #endif 要一起使用,如果丟失#endif,可能會報錯。
需要注意的是,#ifndef起到的效果是防止一個源文件兩次包含同一個頭文件,而不是防止兩個源文件包含同一個頭文件。網上很多資料對這一細節的描述都是錯誤的。事實上,防止同一頭文件被兩個不同的源文件包含這種要求本身就是不合理的,頭文件存在的價值就是被不同的源文件包含。
假如你有一個C源文件,它包含了多個頭文件,比如頭文件A和頭文件B,而頭文件B又包含了頭文件A,則最終的效果是,該源文件包含了兩次頭文件A。如果你在頭文件A裡定義了結構體或者類類型(這是最常見的情況),那麼問題來了,編譯時會報大量的重復定義錯誤。[2]
例如要編寫頭文件test.h
在頭文件開頭寫上兩行:
#ifndef _TEST_H #define _TEST_H//一般是文件名的大寫 頭文件結尾寫上一行: #endif
這樣一個工程文件裡同時包含兩個test.h時,就不會出現重定義的錯誤了。
還是把頭文件的內容都放在#ifndef和#endif中吧。不管你的頭文件會不會被多個文件引用,你都要加上這個。一般格式是這樣的:
#ifndef <標識> #define <標識> ...... ...... #endif
<標識>在理論上來說可以是自由命名的,但每個頭文件的這個“標識”都應該是唯一的。標識的命名規則一般是頭文件名全大寫,前面加下劃線,並把文件名中的“.”也變成下劃線,
在c語言中,對同一個變量或者函數進行多次聲明是不會報錯的。所以如果h文件裡只是進行了聲明工作,即使不使用# ifndef宏定義,一個c文件多次包含同一個h文件也不會報錯。 使用#ifndef可以避免下面這種錯誤:如果在h文件中定義了全局變量,一個c文件包含同一個h文件多次,如果不加#ifndef宏定義,會出現變量重復定義的錯誤;如果加了#ifndef,則不會出現這種錯.
“ 條件編譯”命令允許對程序中的內容選擇性地編譯,即可以根據一定的條件選擇是否編譯。
條件編譯的命令主要有以下幾種 :
形式1
#ifndef標識符 程序段1 #else 程序段 2 #endif
它的作用是當 “ 標識符”沒有由# define定義過了。則編譯“ 程序段 1 ” 。 否則編譯“ 程序段 2 ” 。
形式2
#ifndef 標識符 # define標識符 程序段 1 #else 程序段 2 #endif
它的作用是當 “ 標識符 沒有由# define定義過。 則編譯“程序段 1”。否則編譯“程序段 2” 。同樣當無“ 程序段2 ”時。
形式3
#if表達式 程序段 1 #else 程序段 2 #endif
它的作用是 當“表達式”值為真時。編譯程序段1。否則則編譯程序段2。
以上三種形式的條件編譯預處理結構都可以嵌套使用。 當#else後嵌套 #if 時,可以使用預處理命令# elif , 它相當於 #else#if。在程序中使用條件編譯主要是為了方便程序的調試和移植。