2015-07-10 129 views
0

例如,我想要兩個頭文件,它們可以依賴於另一個頭文件中的函數。爲什麼頭文件Head1.h不能包含一個包含Head1.h的頭文件Head2.h?

//Header1.h file 
#include Header2.h 
void h1(){ 
    //... 
    func1(); 
} 
void h2(); 

//Header2.h file 
#include Header1.h 
void func1(); 
void func2(){ 
    //some other code... 
    h2(); 
} 

這可能不是似乎什麼大問題,但爲了某些文件是邏輯嚴謹,我有時候想這種依賴。在編譯C++代碼時,我在Visual Studio中多次遇到此問題。但是,當我包括每個文件的相應的頭守衛這甚至從來沒有編制,即

#ifndef HEADER1_H 
#define HEADER1_H 
//Header1.h... 
#endif 

爲什麼沒有這可以嗎?或者,有什麼方法可以編譯這個,所以它會起作用嗎?

+2

參見[向前聲明]建議(HTTP://計算器。com/questions/4757565/c-forward-declaration) – Miki

+0

請勿將標題中的定義。 –

回答

4

首先,#include預處理指令執行完整文本替換一個文本文件到另一個文本文件。兩個頭文件試圖彼此形成嵌套文本替換的無限循環。我認爲應該很明顯,無限循環的文本替換不會「起作用」,因爲它是無限的。

其次,使用#ifndef在頭文件中包含守護將在某個點簡單地破壞無限循環。即通函將變爲連續包含一個文件包含第一個和另一個文件包括第二個。但順序包含(以任何順序)將無助於解決您的頭文件中存在的任何圓形聲明依賴關係。由於這個原因,不管你使用的是否包含include防護,頭文件的循環包含從來沒有任何意義(除了形式非常特殊的上下文,像預處理技巧)。循環包容從未達到任何目的。你必須設計你的頭文件,這樣他們甚至不會試圖依賴循環包含。即您必須將您的聲明和頭文件分層爲更低層次和更高層次的文件,並且總是將低層次包含到更高層次(但不是反過來),並通過使用低層前向聲明來解決任何循環聲明依賴性頭。

有時頭文件只是因爲設計不好而需要循環包含。例如,即使聲明之間沒有循環依賴關係,這些聲明可能會錯誤地分佈在頭文件之間,從而導致需要將頭標循環地包含在彼此中。在這種情況下,爲了消除任何循環聲明依賴性,重構頭文件總是一個更好的主意。例如。在頭文件之間重新分配聲明,將兩個相互依賴的頭文件的一部分抽取到第三個低層頭文件中等等。只有當這種重構不可能時,即你有真正的循環聲明依賴性時,才使用前向聲明作爲最後的手段。

1

當您在Header2.h中包含Header1.h時,您正在創建循環依賴關係,反之亦然。

1)將每一個函數的定義中.cpp文件:您可以通過以下兩種方式之一解決它

//Header1.h file 
void h1(); 
void h2(); 

//Header2.h file 
void func1(); 
void func2(); 

//my1.cpp file 
#include Header1.h 
#include Header2.h 
void h1(){ 
    //... 
    func1(); 
} 
void h2() { 
} 

//my2.cpp file 
#include Header1.h 
#include Header2.h 
void func1() { 
} 
void func2(){ 
    //some other code... 
    h2(); 
} 

2)通過@Miki結賬What are forward declarations in C++?