C C 中標頭檔案相互包括引發的問題

2022-09-18 21:45:12 字數 2912 閱讀 9105

今天下午遇到乙個標頭檔案相互包括而導致的編譯問題,花了我不少時間去除錯沒找到問題。最後晚上跟師兄討論不少時間,突然有所頓悟!

我把問題脫離於專案簡單描寫敘述一下:我寫了乙個函式bool func(classa* ca)須要加到專案中,我就把這個函式的宣告放到head1.h中,函式引數型別 classa 定義在還有乙個標頭檔案head2.h中,因此我須要在head1.h中包括head2.h;而head2.h中之前又包括了head1.h。這樣就構成了一種標頭檔案相互包括的場景。再加上一些其他的宣告與定義,就構成了這種乙個檔案結構:

#ifndef __head_1_h__

#define __head_1_h__

#include "head2.h"

#define var_macro 1

//define a macro, which used in head2.h

bool

func

(classa*ca

);//classa is defined in head2.h

#endif

#ifndef __head_2_h__

#define __head_2_h__

#include "head1.h"

class

classa

;//macro var_macro is defined in head1.h

...//other members and functions

};#endif

那麼,如今另有兩個原始檔

#include "head1.h"

//... some source code

#include "head2.h"

//... some source code

整個專案會分別編譯這兩個原始檔,編譯完之後會報錯。大致意思是 classa 和 var_macro 未定義,那麼問題就比較奇怪了。每乙個標頭檔案都分別引用了還有乙個標頭檔案,為什麼會出現未定義呢?

我們都知道 c/c++ 中標頭檔案開始習慣使用#ifndef ... #define ... #endif這種一組預處理識別符號來防止反覆包括。比如上面的問題中我也使用了,假設不使用的話,兩個標頭檔案相互包括。就出現遞迴包括。這個非常好理解就不多敘。

回到問題本身,我在微博上貼出了這個問題。有人說在head1.h的函式前加上classa

a;的前置宣告,至於為什麼要加,預計非常多人都沒理解...

對於source1.cpp,它包括了標頭檔案head1.h。那麼在編譯之前,在source1.cpp中展開head1.h,而head1.h又包括了head2.h

那麼也展開它,這時source1.cpp就變成類似以下這樣:

class

classa

;//macro var_macro is defined in head1.h

...//other members and functions

};#define var_macro 1

//define a macro, which used in head2.h

bool

func

(classa*ca

);//classa is defined in head2.h

//... source1.cpp source code

看到沒,這地方 func 函式之前有 classa 型別的定義,根本不是必需像有些人說的那樣加上classa ca;這種前置宣告。

我們再展開source2.cpp看看:

#define var_macro  1          

//define a macro, which used in head2.h

bool

func

(classa*ca

);//classa is defined in head2.h

class

classa

;//macro var_macro is defined in head1.h

...//other members and functions

};//... source2.cpp source code

這時問題就非常清楚了。func 函式宣告之前並沒有發現 classa 型別定義,該定義在函式宣告的後面,這時候假設能在head1.h的函式宣告之前加上classa

ca;的前置宣告。就不會在編譯的時候報找不到 classa 的定義的錯誤了。

再回到source1.cpp展開的源**看看。是不是一下子明確了為什麼報找不到 var_macro 的定義的錯誤了?改動方法也簡單,把巨集定義拉到#include

"head2.h"語句之前就 ok 了。

如今回頭想想這個問題。事實上是個非常easy的標頭檔案包括的問題。假設了解一些編譯器的預編譯過程,錯誤原理也非常easy。

但為什麼我卡在這個問題非常長時間,原因有下面幾點:

總的來說。遇到問題不要慌,保持大腦清醒,把加一行或減一行**期望就能碰運氣編譯通過的時間拿來分析問題更有效,解決這個問題之後一定確定自己是否知其然亦知其所以然!

google找了一圈。沒找到有價值的資料....

C C 中標頭檔案相互包含引發的問題

今天下午遇到乙個標頭檔案相互包含而導致的編譯問題,花了我不少時間去除錯沒找到問題,最後晚上跟師兄討論不少時間,突然有所頓悟!我把問題脫離於專案簡單描述一下 我寫了乙個函式bool func classa ca 需要加到專案中,我就把這個函式的宣告放到head1.h中,函式引數型別 classa 定義...

C C 中標頭檔案相互包含引發的問題

今天下午遇到乙個標頭檔案相互包含而導致的編譯問題,花了我不少時間去除錯沒找到問題,最後晚上跟師兄討論不少時間,突然有所頓悟!我把問題脫離於專案簡單描述一下 我寫了乙個函式bool func classa ca 需要加到專案中,我就把這個函式的宣告放到head1.h中,函式引數型別 classa 定義...

c 中標頭檔案的相互依賴引發的問題

先上 摘自essential c triangular.h include triangular iterator.h class triangular triangular iterator.h include triangular.h class triangular iterator inli...