#ifndef 是"if not defined"的簡寫,是預處理功能(宏定義、文件包含、條件編譯)當中的條件編譯,可以根據是否已經定義了一個變量來進行分支選擇,其作用是:
1、防止頭文件的重復包含和編譯;
2、便於程序的調試和移植;
下面分別舉例描述。
一、防止頭文件的重復包含和編譯
下面是錯誤示范:
headfile_1.h
1 #include <iostream> 2 class CTest_1 { 3 CTest_1() { 4 //do something,eg:init; 5 } 6 ~CTest_1() { 7 //do something ,eg:free; 8 } 9 void PrintScreen() 10 { 11 std::cout << "this is Class CTest_1!" << std::endl; 12 } 13 };
headfile_2.h
1 #include "headfile_1.h" 2 class CTest_2 { 3 CTest_2() { 4 //do something,eg:init; 5 } 6 ~CTest_2() { 7 //do something,eg:free; 8 } 9 void PrintScreen() 10 { 11 std::cout << "this is Class CTest_2!" << std::endl; 12 } 13 };
sourcefile.cpp
1 #include <iostream> 2 #include "headfile_1.h" 3 #include "headfile_2.h" 4 5 int main() 6 { 7 return 0; 8 }
編譯時提示重定義錯誤:
以上顯示headfile_1.h中的類CTest_1重定義了。
一般地,假如有一個C源文件(如sourcefile.cpp),它包含兩個頭文件(如headfile_1.h和headfile_2.h),而頭文件headfile_2.h又包含了headfile_1.h,則最終的效果是該源文件包含了兩次headfile_1.h。如果你在頭文件里定義了結構體或者類類型,那么問題來了,編譯時將會報重復定義的錯誤。
加上條件編譯"ifndef"則問題可解決。在headfile_1.h中加上條件編譯,如下:
headfile_1.h
1 #ifndef _HEADFILE_1_H 2 #define _HEADFILE_1_H 3 #include <iostream> 4 class CTest_1 { 5 CTest_1() { 6 //do something,eg:init; 7 } 8 ~CTest_1() { 9 //do something ,eg:free; 10 } 11 void PrintScreen() 12 { 13 std::cout << "this is Class CTest_1!" << std::endl; 14 } 15 }; 16 17 #endif //end of _HEADFILE_1_H
編譯通過!
分析:當第一次包含headfile_1.h時,由於沒有定義_HEADFILE_1_H,條件為真,這樣就會執行#ifndef _HEADFILE_1_H和#endif之間的代碼;當第二次包含headfile_1.h時,前面一次已經定義了_HEADFILE_1_H,條件為假,#ifndef _HEADFILE_1_H和#endif之間的代碼也就不會再次被包含,這樣就避免了重定義。
小結:還是把頭文件的內容都放在#ifndef和#endif中吧。不管你的頭文件會不會被多個文件引用,你最好都加上這個。一般格式是這樣的:
#ifndef <標識> #define <標識> ...... ...... #endif
<標識>在理論上來說是可以自由命名的,但每個頭文件的這個“標識”都應該是唯一的。標識的明明規則一般是頭文件名全大寫,前面加下划線,並把文件名中的"."也變成下划線,如:stdio.h
#ifndef _STDIO_H #define _STDIO_H ...... ...... #endif
注意:#ifndef起到的效果是防止一個源文件多次包含同一個頭文件,而不是防止兩個源文件包含同一個頭文件。事實上,防止同一頭文件被兩個不同的源文件包含這種要求本身就是不合理的,頭文件存在的價值就是被不同的源文件包含。
二、便於程序的調試和移植
在調試程序時,常常需要對程序中的內容進行選擇性地編譯,即可以根據一定的條件選擇是否編譯。
主要分以下幾種:
1、
#ifndef 標識符 程序段 1 #else 程序段 2 #endif
它的作用是當“標識符”沒有由#define定義過,則編譯“程序段1”,否則編譯“程序段2”。
2、
#ifndef 標識符 #define 標識符 程序段 1 #else 程序段 2 #endif
它的作用是當“標識符”沒有由#define定義過,則編譯“程序段1”,否則編譯“程序段2”。
3、
#if 表達式 程序段 1 #else 程序段 2 #endif
它的作用是當“表達式”值為真時,編譯“程序段1”,否則編譯“程序段2”。
注:以上三種形式中#else不是強制的,可省略;當然,當#else后需要嵌套#if時,可以使用預處理命令#elif,它相當於#else#if。
小結:在程序中使用條件編譯主要是為了方便程序的調試和移植。