Re: [問題] .h宣告和定義分開的理由

看板C_and_CPP作者 (艾斯寇德)時間15年前 (2009/04/07 12:13), 編輯推噓0(007)
留言7則, 2人參與, 最新討論串3/4 (看更多)
※ 引述《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

04/07 12:35, , 1F
其實header本來就是為了分檔用。把一個大程式拆成很多個
04/07 12:35, 1F

04/07 12:36, , 2F
source編譯成很多個object,最後才全部連結起來。
04/07 12:36, 2F

04/07 12:37, , 3F
如果不分檔,那麼每次改一點東西就要花很多時間重編譯。
04/07 12:37, 3F

04/07 12:38, , 4F
而分檔過的程式則可以針對被改過的source file重新編譯
04/07 12:38, 4F

04/07 12:39, , 5F
成object然後再跟之前沒動到的object做連結,省下不必要
04/07 12:39, 5F

04/07 12:39, , 6F
的編譯時間。
04/07 12:39, 6F

04/07 12:38, , 7F
原來如此 感謝樓上的說明 <(_ _)>
04/07 12:38, 7F
※ 編輯: sunneo 來自: 61.227.112.207 (04/07 12:45)
文章代碼(AID): #19sjBL_1 (C_and_CPP)
文章代碼(AID): #19sjBL_1 (C_and_CPP)