作者poolongkong (普拢贡)
看板C_and_CPP
标题[问题] 专案中的 include/lib 资料夹该放什麽
时间Sun Jul 12 20:42:57 2020
其实小弟想发问的问题有两个,
首先是如标题说明的,在一个专案里的 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://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1594557782.A.F1C.html
※ 编辑: poolongkong (36.226.233.170 台湾), 07/12/2020 20:44:47
1F:→ nh60211as: 那个实作在.h应该是因为template不能实作在.cpp 07/12 21:50
2F:→ nh60211as: 不然会link time error,其他不清楚请别人回答了 07/12 21:50
3F:→ Lipraxde: 比较细节的放 lib,其他的放 include,毕竟写在 header 07/12 23:14
4F:→ Lipraxde: 里真的太方便了(x 07/12 23:14
5F:推 Dracarys: 除了template的原因,我猜大概是为了方便inline 07/12 23:22
谢谢楼上板友们的回覆,我还真的忘了 template 的问题
6F:→ loveme00835: 你觉得介面实作分开是为了什麽? 07/13 03:27
我个人会认为是为了好维护以及节省编译时间,
但依稀有印象,在求学阶段有听过其中一个是安全性的原因,
不过安全性的部份我倒是不太懂...
但l大会这样问应该是我的问题叙述不恰当,已更正了!
我想问的其实是介面与实作分开这件事该怎麽做比较适合,
比如说是什麽样的 member function 应该在 header file 实作就好,什麽样的
member function 又会比较适合在 .cpp 档实作,
(例如大部分的 template 会实作在 header file)
※ 编辑: poolongkong (36.226.233.170 台湾), 07/13/2020 03:47:24
7F:→ loveme00835: 把东西放在标头档再分离编译的情况, 对不同的 transl 07/13 03:43
8F:→ loveme00835: ation unit 来说, 引入的多份型别/模板/物件彼此其实 07/13 03:43
9F:→ loveme00835: 是不一样的; 但因为要保证 ODR 所以它们被视为是相同 07/13 03:43
10F:→ loveme00835: 的实体. 即使模板也可以细分有无特化/具现化, 一般最 07/13 03:43
11F:→ loveme00835: 简单的使用通常都是无特化再透过 implicit instantia 07/13 03:43
12F:→ loveme00835: tion 来自动产生实作, 因为要完整的程式码才有办法做 07/13 03:43
13F:→ loveme00835: 的这件事, 所以才会有模板实作都要写在标头档的错觉. 07/13 03:43
14F:→ loveme00835: 事实上模板也可以写成像你说的一样: 介面/实作分离, 07/13 03:43
15F:→ loveme00835: 但要很明白你的目的, 因为这种写法很容易违反 ODR. 07/13 03:43
刚刚回覆第一则推文的时候还没看到这些 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
16F:→ loveme00835: 先明白 include 只是复制贴上, 那再来从 ODR 的角度 07/13 03:52
17F:→ loveme00835: 思考为什麽有的东西可以放在标头档里其他的却会造成 07/13 03:52
18F:→ loveme00835: 连结错误, 再来想想这样分开写到底有什麽好处. 如果 07/13 03:52
19F:→ loveme00835: 今天我分开写没办法得到上述的好处, 也不会造成连结 07/13 03:52
20F:→ loveme00835: 错误的话, 当然全写在标头档里比较方便罗 (节省同步 07/13 03:52
21F:→ loveme00835: 的成本). 07/13 03:52
所以其实界面与实作分开是要根据使用情境去做一些 trade off 吗?
(比如上面提到的 template 这样)
※ 编辑: poolongkong (36.226.233.170 台湾), 07/13/2020 04:01:23
22F:→ loveme00835: 开发软体最经常遇到的就是改变, 最害怕的也是改变. 07/13 04:02
23F:→ loveme00835: 开发上分成两个角色: library user & developer. use 07/13 04:02
24F:→ loveme00835: r 因为只是不需要知道细节, 所以有一份标头档和已经 07/13 04:02
25F:→ loveme00835: 编好的函式库档就可以做开发, developer 有任何改动, 07/13 04:02
26F:→ loveme00835: 如果不是改在标头档内, 所以 user 所需要做的最多就 07/13 04:02
27F:→ loveme00835: 是重新连结而已. 介面/实作分离一方面就是要避免 use 07/13 04:02
28F:→ loveme00835: r 重复做编译的动作 (编译防火墙), 如果函式库含有商 07/13 04:02
29F:→ loveme00835: 业机密通常也会这样做 (看授权) 所以撰码的时候身分 07/13 04:02
30F:→ loveme00835: 需要持续切换, 作为 developer 时就要思考怎样让 use 07/13 04:02
31F:→ loveme00835: r 减少编译次数, 在介面上做最少改动; 作为 user 的 07/13 04:02
32F:→ loveme00835: 时候思考介面设计是否方便合理. 07/13 04:02
33F:→ loveme00835: 简单说如果一个实作万年不变, 而且没有需要/可能减少 07/13 04:06
34F:→ loveme00835: 编译次数/时间的考量, 就会直接写在标头档里. 07/13 04:06
大概明白了,感谢l大!!
之前都觉得界面与实作分开是一种绝对的关系,
所以一直以为可能有某种规则存在,
如果符合该规则就是实作在 header,不符合就实作在 .cpp 档之类的情况,
原来跟我想的完全不一样... Orz
※ 编辑: poolongkong (36.226.233.170 台湾), 07/13/2020 04:12:20
35F:→ loveme00835: 以 ISO 标准教学流程 [P1389R1] 来说这个应该归在最 07/13 05:20
36F:→ loveme00835: 後的工具介绍阶段里, 对语言特性更了解後才比较清楚 07/13 05:20
37F:→ loveme00835: 该怎麽拿捏. 只是为了教学方便很容易跳过这些基础知 07/13 05:20
38F:→ loveme00835: 识, 不过关键字: ODR 可以先深入学习. 07/13 05:20
等等空闲的时间来看一下相关资料,再次感谢l大!!
※ 编辑: poolongkong (140.113.193.216 台湾), 07/13/2020 13:26:26
39F:推 ofd168: 每次看love大的推文都能学到很多 07/21 09:30