防止標頭檔案重複包含的兩種方法及區別

2021-07-10 18:51:52 字數 2147 閱讀 5207

1.條件編譯語句#ifndef#define#endif

相信很多人都知道第一種方法。

#ifndef _test_h_    //——1

#define _test_h_ //——2

//加入各種變數,函式宣告

#endif

//——3

以上**:如果沒有定義test_h變數,就繼續往下執行,如果定義了,就直接endif,即不做任何操作。

如果乙個檔案中包含了兩個同樣的標頭檔案,那麼第一次呼叫這個標頭檔案的時候,沒有定義test_h,經過1,到達2,定義test_h,進行**段的執行,到3結束。但是當第二次呼叫標頭檔案時,已經定義了test_h,所以就不會進行下面的**宣告了。這就是條件編譯進行防止標頭檔案包含的原理

所以可以用條件編譯語句進行防止乙個檔案中重複包含標頭檔案。

這個方法被廣為人知,但是,一般在乙個工程中,我們至少要加入main.cpp,function.cpp,function.h三個檔案。乙個為主函式檔案,乙個為標頭檔案,用於宣告變數,類,類模板或函式等,功能檔案用來定義函式。

通常我們在main.cpp和function.cpp都會引入#include 「function.h」檔案。

在這裡我再贅述一下c,c++中檔案編譯鏈結的順序:

第乙個階段是預處理階段,在正式的編譯階段之前進行。預處理階段將根據已放置在檔案中的預處理指令來修改原始檔的內容。如#include指令就是乙個預處理指令,它把頭檔案的內容新增到.cpp檔案中。

第二個階段編譯、優化階段,將其翻譯成等價的中間**表示或彙編**,並執行優化。

第三個階段是彙編,把組合語言**翻譯成目標機器指令。

第四個階段是鏈結,例如,某個原始檔中的函式可能引用了另乙個原始檔中定義的某個符號(如變數或者函式呼叫等);在程式中可能呼叫了某個庫檔案中的函式,等等。所有的這些問題,都需要經鏈結程式的處理方能得以解決。

在編譯階段,每個檔案是分別編譯的,在編譯階段我們可以通過條件編譯的方法去防止標頭檔案重複包含,但是由於巨集是在編譯之前處理的,

即巨集的功能僅僅只能體現在編譯階段,因此#ifndef #define #endif語句只能防止編譯階段的「重複包含」錯誤。在鏈結時,由於鏈結器的作用是將編譯器生成的.obj檔案鏈結起來並生成最終可執行檔案,因此鏈結器的作用範圍是「檔案之間」。不會再去處理巨集預處理指令,所以條件編譯這個方法只能在編譯階段防止重複包含,如果在標頭檔案中進行了定義,即使用了條件編譯語句,在鏈結的時候也會報重定義錯誤。

其實只要在標頭檔案進行宣告,不進行定義,就不會出錯。因為定義不能定義兩次,但是宣告可以宣告多次。

總結:條件編譯語句可以防止乙個檔案中對頭檔案的重複包含,其實也不是沒有用的,如果乙個檔案a.c中包含了標頭檔案a.h和b.h,但是標頭檔案a.h中也包含了b.h,那麼條件編譯語句就會發揮作用,經過編譯生成的.obj檔案中只會乙個b.h檔案

注意:即使重複包含,預處理器仍將整個標頭檔案讀入,即使這個標頭檔案所有內容將被忽略。由於這種處理將減慢編譯速度,所以如果可能,應該避免出現多重包含

所以單獨使用條件編譯語句僅僅防止了重複包含標頭檔案的問題,並沒有解決重複定義的問題

條件編譯語句還有乙個缺點,就是包含了不同的標頭檔案時,如果不同標頭檔案的巨集名不小心「撞車」,可能就會導致標頭檔案明明存在,編譯器卻硬說找不到宣告的狀況。

2.#pragma once語句

//方式一:

#ifndef _somefile_h_

#define _somefile_h_

//.......... // 一些宣告語句

#endif

//方式二:

#pragma once

//...

... // 一些宣告語句

以上就是兩種方法的區別。

pragma once由編譯器提供保證:

同乙個檔案不會被編譯多次。注意這裡所說的「同乙個檔案」是指物理上的乙個檔案,而不是指內容相同的兩個檔案。

帶來的好處是,你不必再費勁想個巨集名了,當然也就不會出現巨集名碰撞引發的奇怪問題。對應的缺點就是如果某個標頭檔案有多份拷貝,本方法不能保證他們不被重複包含。當然,相比巨集名碰撞引發的「找不到宣告」的問題,重複包含更容易被發現並修正。

防止標頭檔案重複包含的兩種方法及區別

在編譯階段,每個檔案是分別編譯的,在編譯階段我們可以通過條件編譯的方法去防止標頭檔案重複包含,但是由於巨集是在編譯之前處理的,即巨集的功能僅僅只能體現在編譯階段,因此 ifndef define endif語句只能防止編譯階段的 重複包含 錯誤。在鏈結時,由於鏈結器的作用是將編譯器生成的.obj檔案...

防止標頭檔案重複包含方法

編譯器支援 標準未定義 由編譯器保證不會重複包含物理上的同乙個檔案 ifndef test.h define test.h code endif 條件編譯是標準支援的 因為標準支援 define定義的識別符號 不會重複引入同名的檔案 存在不小心寫錯define識別符號導致重複引入的問題 所以有些c標...

防止標頭檔案重複包含

在程式設計中,經常會遇到這種情況,我們的某乙個程式會呼叫多個dll,因此需要包含多個標頭檔案,不同的標頭檔案可能包含了相同某乙個下一級標頭檔案,這就可能會導致標頭檔案的重複包含,從而導致變數 函式的重定義等等,為了解決這個問題,就要求我們在編寫dll的時候,使用 ifndef define endi...