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

2021-07-22 22:36:25 字數 2861 閱讀 6362

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

我把問題脫離於專案簡單描述一下:我寫了乙個函式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 了。

現在回頭想想這個問題,其實是個非常簡單的標頭檔案包含的問題,如果了解一些編譯器的預編譯過程,錯誤原理也很簡單。但為什麼我卡在這個問題很長時間,原因有以下幾點:

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

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...