作者sunneo (艾斯寇德)
看板C_and_CPP
標題Re: [問題] .h宣告和定義分開的理由
時間Tue Apr 7 12:13:06 2009
※ 引述《godman362 (Shizuru)》之銘言:
: 小弟寫程式也三年了
: 最近開始邁入小型的專案開發
: 但是我看了很多專案的程式碼
: 大多都是將.h檔的定義和宣告分開來放
: 我看過較多的說法是說不想將實作公開出來
: 但是我覺得這個說法似乎有些微的牽強
: 所以想請問一下各位先進,真正分開做的理由是甚麼?
: 還請各位指點一番。
有時候是因為實做的各個c/cpp檔案裡面可以存在static function(private function)
在有些時候,你不希望使用者直接修改你的變數內容或者結構體資訊時,你會把
結構體包成Handle (void*),這可以達成encapulation的效果。
將定義跟宣告分開,除了意外的你得到了一個附加的api,也可以免除維護上的困難,
(不管你有沒有得到一個附加的api,函式說明還是以document輸出的好。)
但最主要克服的還是在linker上的工作,如果你的實作不是inline且不是template
更不是class的implicit inline,那麼你就會在linker階段碰上問題,
今天你在cpp 1裡面因為header得到了global var A,cpp 1被編譯為obj1
cpp2經由header得到了A的實體,
所以也來了個global var A,而你的專案需求是這兩個obj要結合成一個檔案
這時候就出現了重複定義的情況。
發佈成dll的時候,差別就是你一定要把實作跟宣告分開,且要發佈的進入點如果不是
inline/template,那就要用__declspec(dllexport) 修飾,在釋出檔要把header的
dllexport改為dllimport。
比如你在建立一個dll專案時會出現
#if BUILDING_DLL
# define DLLAPI __declspec(dllexport)
#else
# define DLLAPI __declspec(dllimport)
#endif
發布的格式如
DLLAPI RET_T FunctionName();
struct DLLAPI StructName{
...
};
class DLLAPI ClassName{
...
};
typedef,enum 的型別就不用了,這是compile階段的。
全域變數
extern DLLAPI TYPE VARNAME;
假使全域變數是一個function pointer時也要匯出
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.227.112.207
→ Bencrie:其實header本來就是為了分檔用。把一個大程式拆成很多個 04/07 12:35
→ Bencrie:source編譯成很多個object,最後才全部連結起來。 04/07 12:36
→ Bencrie:如果不分檔,那麼每次改一點東西就要花很多時間重編譯。 04/07 12:37
→ Bencrie:而分檔過的程式則可以針對被改過的source file重新編譯 04/07 12:38
→ Bencrie:成object然後再跟之前沒動到的object做連結,省下不必要 04/07 12:39
→ Bencrie:的編譯時間。 04/07 12:39
→ sunneo:原來如此 感謝樓上的說明 <(_ _)>04/07 12:38
※ 編輯: sunneo 來自: 61.227.112.207 (04/07 12:45)