2012-09-06 157 views
5

爲什麼要聲明您作爲頭文件包含的類?爲什麼要聲明您作爲頭文件包含的類?

#include "TreeCallObj.h" 
#include "TreeDevObj.h" 
#include "TreeDevCallObj.h" 

class TreeCallObj; //what is the purpose of this line ? 
class TreeDevObj; //what is the purpose of this line ? 
class TreeDevCallObj; //what is the purpose of this line ? 


class Apple 
{ 
public: 
... 
private: 
... 
} 
+1

好像我們錯過了一些上下文。可能有一些循環頭文件引用正在進行,並且'TreeWhateverObj'類僅在當前文件中由指針引用?也許它只是由真正喜歡他們的轉發定義的人寫的。在'Obj'後綴類名看起來像是一個瘋狂的編碼約定對我的警報。 – Rook

+0

我讀過如果項目需要10分鐘才能構建,那麼聲明該類可以提高編譯時間?我不知道這是多麼真實,以及多大的收益。 – jdl

+0

聽起來不太可能,但也相當簡單的測試。讓我們知道它是怎麼回事;-) – Rook

回答

6

考慮一下:

//a.h 
#ifndef A_H 
#define A_H 

#include "b.h" 
class A 
{ 
    B* b; 
}; 
#endif 

//b.h 
#ifndef B_H 
#define B_H 

#include "a.h" 
class B 
{ 
    A* a; 
}; 
#endif 

現在你嘗試加入的一個文件在不同的一個,說你#include "a.h"

編譯器會分析它爲:

#ifndef A_H 
#define A_H 

精 - A_H沒有定義

#include "b.h" 

嘗試粘貼的內容:

#ifndef B_H 
#define B_H 

OK,既然B_H ISN沒有定義

#include "a.h" 

這不會定義A,因爲A_H已定義。所以接下來,我們有

class B 
{ 
    A* a; 
}; 

這將導致一個錯誤,因爲A沒有定義或使用之前聲明。

前向聲明修復了這一點。

當然,,最好的解決方案是根本不包括(除非你絕對必須)。

+1

號如果在第三種情況下'A_H'已經被定義了,那麼類'A'也會在同樣的範圍內被定義。 –

+0

@EitanT否,因爲在定義A之前,A.h包含B.h。對? –

+0

「這不會定義A,因爲A_H是被定義的,所以接下來我們有 - 」是的,這就是包含衛兵的要點。如果定義了A_H,那麼A類已經被聲明 - 沒有錯誤。 – 2012-09-06 15:43:16

3

如果文件存在的類定義,因此,forward declaration是在正常情況下是不必要的。

5

這條線的目的是什麼?

理想情況下什麼都沒有。這是多餘的。

但是,正如@Luchian Grigore指出的那樣,可能會有這樣一個設計錯誤的代碼,由於不正確地使用include guard和cross-includes,前向聲明可能是必需的。

+0

@LuchianGrigore是的。你是對的。 – 2012-09-06 15:46:25

+0

我不一定是設計糟糕的代碼。這只是循環依賴。 –

+0

@EitanT嗯,我認爲是的。如果一個人無法在沒有交叉引用的情況下解決問題,那麼設計上就會出現問題。您能否提供一個例子,您認爲這是一種很好的方法? – 2012-09-06 15:50:32

1

沒有理由。你需要做一個或另一個,取決於情況,但不是兩個。

0

如果你的頭文件是正確的,我看到沒有任何意義,因爲宣佈,他們應該在標題

1

因爲它的立場已經聲明,就沒有必要。

然而,這可能是歷史上形成:在某些時候,一個不完整的類型可能已經夠了:

class Foo; 

struct Gizmo 
{ 
    void f(Foo); 
}; 

然後,在以後,筆者決定了她所需要的完整的類型:

#include "Foo.hpp" 

class Foo; 

struct Gizmo 
{ 
    void f(Foo); 
    Foo x; 
}; 

原始代碼可能只是已經修改與現在,必要的頭包...

+0

或者'struct Gizmo {Foo * foo; }'後來改成'struct Gizmo {Foo foo; }'。所以對於前者,聲明'class Foo;'就足夠了,但是對於後者,定義是必需的,因此'#include「foo.hpp」'。 :-) – Nawaz

+0

@Nawaz:是的!但我不想向任何人推薦'Foo *'是可以接受的C++ :-)我一會兒就在用'unique_ptr '玩弄...... –

+0

當你談論*歷史*時,你可以談論'Foo * '*舒服* ;-)。沒有人會冷落你:P(呃,至少我不是)。 – Nawaz

1

我猜想有一些歷史了這一點。編碼器最初試圖不包含頭文件,而是使用前向聲明。然後,隨着代碼擴展,他們發現他們最終需要頭文件,但沒有打算刪除前向聲明。

正如其他人所說的那樣,在課堂申報之後進行前瞻性聲明沒有任何意義。

1

我注意到你的頭沒有防止多重包含。也有可能是一些包含的其他頭文件(頭文件通常有這樣的警衛)包含了頭文件。結果它沒有編譯。所以有人添加了前向聲明來修復錯誤的bug。

相關問題