C++ 中類的聲明和類的定義分開幾乎成了一個不成文的規定。這樣做的好處是使得類的聲明和實現分開,清晰明了,同時便於庫函數發布。但是在實際編程中由此也常常 引起了一些由於頭文件的包含順序問題而產生的符號未定義的編譯錯誤,不明白其中原理有時會讓人很頭疼。要消除符號未定義的錯誤的編譯錯誤,最基本的一個做 法就是在引用一個符號(包括變量,函數,結構,類等)之前確保它已經聲明或者已經定義。
實際中編碼設計過程中,最基本的一個原則就是在類的頭文件中最好不要包含其他頭文件,因為這樣會使類之間的文件包含關系變得復雜化。要最大限度的遵守這個原則,實際編碼設計過程可以采用以下兩種方法:
方法一是在設計一個類的時候盡量保持類的獨立性,即使該類盡可能不要依賴其他類庫或者函數庫,或者退一步來說,盡量不要在類的聲明中依賴其他類。這樣,在 該類的聲明頭文件中就可以沒有其他頭文件。如果實現中用到了其他的類,那麼可以只在該類的實現文件中包含用到的類庫或者函數庫的頭文件就行。
方法二是當類的聲明中必須得用到其他類庫或者函數庫時,方法一便不再適用,當一個類聲明中引用的是其他類或結構的指針引用或者是函數引用時,也可以保持上 述原則,做法是采用前向引用,及在該類的聲明前面先聲明一下該類所用到的類名或者函數名就行。當類聲明中引用的是其他類的實例時,上述原則變不能保持,只 有在該類的聲明頭文件中引用所引用的類庫或者函數庫的頭文件。
然而,實際中,如果一個類要用到很多其他的類指針或者結構指針或者函數名時,雖然采用上述方法二可以保持上述原則,但是在該類的前面將所有用到的類和方法聲明一遍會比較麻煩,這種情況下,為了方便也只好在該類的聲明頭文件中加入其他類庫或者函數庫中的頭文件了。
下面舉幾個例子:www.2cto.com
例子1:最簡單的一種情況:兩個類A和B之間完全沒有關系
這種情況下兩個類的聲明和定義文件中根本不需要包含對方的聲明頭文件。(雖然是廢話,但是很多人的代碼中卻大量存在這種情況下仍然互相包含或者包含頭文件的情況,主要原因:懶,不想多思考)
例子2:兩個類A和B在實現的時候用到了對方
這種情況只需要在每個類的實現文件文件中包含所用到的類的頭文件即可。
例子3:兩個類A和B在聲明的時候通過指針引用到了對方
這種情況下可以在類的聲明(頭文件中)前面聲明一下所用到的類,然後在各自的頭文件中包含所用的類的聲明頭文件。比如:
// A.h
class B;
class A
{
B *pb;
}
// B.h
class A;
class B
{
A *pa;
}
// A.cpp
#inclue "B.h"
#inclue "A.H"
......
// B.cpp
#inclue "A.h"
#inclue "B.h"
......
還有,在大型工程程序設計中,一個類往往需要用到很多已有的類庫及函數庫,把一個類所用到的所有類庫頭文件都加入到類的定義頭文件中往往也非常麻煩,這時 的做法是把那些經常用到的頭文件加入到一個公共的頭文件中,這個公共頭文件在比如叫push.h。要注意的是一些頭文件也有依賴關 系,這些文件的包含順序也小心,否則就會出錯。ps,頭文件的包含順序應該是從最特殊到一般,比如:我們應該以這樣的方式來#include頭文件:
從最特殊到最一般,也就是,
#include "本類頭文件"
#include "本目錄頭文件"
#include "自己寫的工具頭文件"
#include "第三方頭文件"
#include "平台相關頭文件"
#include "C++庫頭文件"
#include "C庫頭文件"