[問題] 專案中的 include/lib 資料夾該放什麼

看板C_and_CPP (C/C++)作者 (普攏貢)時間5年前 (2020/07/12 20:43), 5年前編輯推噓2(2037)
留言39則, 5人參與, 5年前最新討論串1/1
其實小弟想發問的問題有兩個, 首先是如標題說明的,在一個專案裡的 include & lib 資料夾分別代表什麼意思, 我知道跟 header file、static library、shared library 有關, 但我想問的不是在 source code include header file 或是 compile time 的 linker 相關問題, 而是說 "什麼概念的 source code" 該放在 include & lib 資料夾。 第二個問題是 class 的 declaration & definition 到底怎麼寫才是對的, 因為不管是學校或是網路上的入門教學,都會建議介面跟實作要分開, 幾乎所有的例子都是 declaration 放在 .h 檔、definition 放在 .cpp 檔, 所以原本小弟一直以為 class 的 declaration (.h) 就是放在 include、class 的 definition (.cpp) 就是放在 lib, 但看了一些 open source 的專案才發現不是我想的這樣。 以最近在看的 LLVM 的 SmallVector 當例子, (簡單說明一下,SmallVactor 是對 elements 較少的情況而去優化的 vector) 在 LLVM 的 source code 中可以分別找到 SmallVector.h https://code.woboq.org/llvm/llvm/include/llvm/ADT/SmallVector.h.html 以及 SmallVector.cpp https://code.woboq.org/llvm/llvm/lib/Support/SmallVector.cpp.html 但翻一下 code 可以發現幾乎 95% 的功能實作都是在 .h 檔裡面, 並且也沒有所謂的介面與實作分開。 雖然寫了一段時間的程式,但對這一塊真的沒什麼研究, google 也是找到一堆 header file 與 library 之間的差異, 但我想問的不是 link 之類的問題啊~~ 最後再簡述一下問題: 1. 專案中的 include & lib 資料夾中的 source code 應該放什麼概念的 code 才是對的? 2. (X) 介面與實作分開這件事是有必要的嗎? (O) 介面與實作分開這件事該怎麼分割比較適合? 先謝謝看完問題的各位~ -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.226.233.170 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1594557782.A.F1C.html ※ 編輯: poolongkong (36.226.233.170 臺灣), 07/12/2020 20:44:47

07/12 21:50, 5年前 , 1F
那個實作在.h應該是因為template不能實作在.cpp
07/12 21:50, 1F

07/12 21:50, 5年前 , 2F
不然會link time error,其他不清楚請別人回答了
07/12 21:50, 2F

07/12 23:14, 5年前 , 3F
比較細節的放 lib,其他的放 include,畢竟寫在 header
07/12 23:14, 3F

07/12 23:14, 5年前 , 4F
裡真的太方便了(x
07/12 23:14, 4F

07/12 23:22, 5年前 , 5F
除了template的原因,我猜大概是為了方便inline
07/12 23:22, 5F
謝謝樓上板友們的回覆,我還真的忘了 template 的問題

07/13 03:27, 5年前 , 6F
你覺得介面實作分開是為了什麼?
07/13 03:27, 6F
我個人會認為是為了好維護以及節省編譯時間, 但依稀有印象,在求學階段有聽過其中一個是安全性的原因, 不過安全性的部份我倒是不太懂... 但l大會這樣問應該是我的問題敘述不恰當,已更正了! 我想問的其實是介面與實作分開這件事該怎麼做比較適合, 比如說是什麼樣的 member function 應該在 header file 實作就好,什麼樣的 member function 又會比較適合在 .cpp 檔實作, (例如大部分的 template 會實作在 header file) ※ 編輯: poolongkong (36.226.233.170 臺灣), 07/13/2020 03:47:24

07/13 03:43, 5年前 , 7F
把東西放在標頭檔再分離編譯的情況, 對不同的 transl
07/13 03:43, 7F

07/13 03:43, 5年前 , 8F
ation unit 來說, 引入的多份型別/模板/物件彼此其實
07/13 03:43, 8F

07/13 03:43, 5年前 , 9F
是不一樣的; 但因為要保證 ODR 所以它們被視為是相同
07/13 03:43, 9F

07/13 03:43, 5年前 , 10F
的實體. 即使模板也可以細分有無特化/具現化, 一般最
07/13 03:43, 10F

07/13 03:43, 5年前 , 11F
簡單的使用通常都是無特化再透過 implicit instantia
07/13 03:43, 11F

07/13 03:43, 5年前 , 12F
tion 來自動產生實作, 因為要完整的程式碼才有辦法做
07/13 03:43, 12F

07/13 03:43, 5年前 , 13F
的這件事, 所以才會有模板實作都要寫在標頭檔的錯覺.
07/13 03:43, 13F

07/13 03:43, 5年前 , 14F
事實上模板也可以寫成像你說的一樣: 介面/實作分離,
07/13 03:43, 14F

07/13 03:43, 5年前 , 15F
但要很明白你的目的, 因為這種寫法很容易違反 ODR.
07/13 03:43, 15F
剛剛回覆第一則推文的時候還沒看到這些 0.0 我已經知道大部分 template 會實作在 header file 的原因 (就如同l大說的), 但除了 template 之外, 我有看過一個 class 中,部份的 member function 就實作在 header file 裡, 另一部分的實作又放在 .cpp 檔, 這種情況在實務上會有什麼特殊的意義嗎? 還是我看到的只是 coding style 不好的特例... ※ 編輯: poolongkong (36.226.233.170 臺灣), 07/13/2020 03:55:38

07/13 03:52, 5年前 , 16F
先明白 include 只是複製貼上, 那再來從 ODR 的角度
07/13 03:52, 16F

07/13 03:52, 5年前 , 17F
思考為什麼有的東西可以放在標頭檔裡其他的卻會造成
07/13 03:52, 17F

07/13 03:52, 5年前 , 18F
連結錯誤, 再來想想這樣分開寫到底有什麼好處. 如果
07/13 03:52, 18F

07/13 03:52, 5年前 , 19F
今天我分開寫沒辦法得到上述的好處, 也不會造成連結
07/13 03:52, 19F

07/13 03:52, 5年前 , 20F
錯誤的話, 當然全寫在標頭檔裡比較方便囉 (節省同步
07/13 03:52, 20F

07/13 03:52, 5年前 , 21F
的成本).
07/13 03:52, 21F
所以其實界面與實作分開是要根據使用情境去做一些 trade off 嗎? (比如上面提到的 template 這樣) ※ 編輯: poolongkong (36.226.233.170 臺灣), 07/13/2020 04:01:23

07/13 04:02, 5年前 , 22F
開發軟體最經常遇到的就是改變, 最害怕的也是改變.
07/13 04:02, 22F

07/13 04:02, 5年前 , 23F
開發上分成兩個角色: library user & developer. use
07/13 04:02, 23F

07/13 04:02, 5年前 , 24F
r 因為只是不需要知道細節, 所以有一份標頭檔和已經
07/13 04:02, 24F

07/13 04:02, 5年前 , 25F
編好的函式庫檔就可以做開發, developer 有任何改動,
07/13 04:02, 25F

07/13 04:02, 5年前 , 26F
如果不是改在標頭檔內, 所以 user 所需要做的最多就
07/13 04:02, 26F

07/13 04:02, 5年前 , 27F
是重新連結而已. 介面/實作分離一方面就是要避免 use
07/13 04:02, 27F

07/13 04:02, 5年前 , 28F
r 重複做編譯的動作 (編譯防火牆), 如果函式庫含有商
07/13 04:02, 28F

07/13 04:02, 5年前 , 29F
業機密通常也會這樣做 (看授權) 所以撰碼的時候身分
07/13 04:02, 29F

07/13 04:02, 5年前 , 30F
需要持續切換, 作為 developer 時就要思考怎樣讓 use
07/13 04:02, 30F

07/13 04:02, 5年前 , 31F
r 減少編譯次數, 在介面上做最少改動; 作為 user 的
07/13 04:02, 31F

07/13 04:02, 5年前 , 32F
時候思考介面設計是否方便合理.
07/13 04:02, 32F

07/13 04:06, 5年前 , 33F
簡單說如果一個實作萬年不變, 而且沒有需要/可能減少
07/13 04:06, 33F

07/13 04:06, 5年前 , 34F
編譯次數/時間的考量, 就會直接寫在標頭檔裡.
07/13 04:06, 34F
大概明白了,感謝l大!! 之前都覺得界面與實作分開是一種絕對的關係, 所以一直以為可能有某種規則存在, 如果符合該規則就是實作在 header,不符合就實作在 .cpp 檔之類的情況, 原來跟我想的完全不一樣... Orz ※ 編輯: poolongkong (36.226.233.170 臺灣), 07/13/2020 04:12:20

07/13 05:20, 5年前 , 35F
以 ISO 標準教學流程 [P1389R1] 來說這個應該歸在最
07/13 05:20, 35F

07/13 05:20, 5年前 , 36F
後的工具介紹階段裡, 對語言特性更了解後才比較清楚
07/13 05:20, 36F

07/13 05:20, 5年前 , 37F
該怎麼拿捏. 只是為了教學方便很容易跳過這些基礎知
07/13 05:20, 37F

07/13 05:20, 5年前 , 38F
識, 不過關鍵字: ODR 可以先深入學習.
07/13 05:20, 38F
等等空閒的時間來看一下相關資料,再次感謝l大!! ※ 編輯: poolongkong (140.113.193.216 臺灣), 07/13/2020 13:26:26

07/21 09:30, 5年前 , 39F
每次看love大的推文都能學到很多
07/21 09:30, 39F
文章代碼(AID): #1V2mLMyS (C_and_CPP)
文章代碼(AID): #1V2mLMyS (C_and_CPP)