我一直在关注Boost和其他各种C ++库。绝大多数Boost都是在头文件中实现的。
我的问题是:在什么条件下你做了一个只有头的实现(比如Boost)还是包含.cpp文件?
答案 0 :(得分:7)
如果要在另一个翻译单元(即另一个源文件)中使用模板,则应该(几乎总是)在头文件中定义它。 (也有例外,如下面的评论所指出的,但恕我直言,这是一个很好的经验法则。)
如果您想使用其他翻译单元的内联函数,则同样适用。
否则,您应该将实现放入单独的.cpp文件中以最小化依赖性。
答案 1 :(得分:3)
理解这个问题基本上是要了解C ++编译单元的工作原理。头文件中的内容基本上被#include
语句粘贴到一大堆编译单元的源代码中。每个编译单元都被编译成一个目标文件,目标文件被链接起来,并且由于这些东西被整个地方复制而产生冲突。
例外是(历史上至少)不会进入目标文件的事情,因为编译器直接处理它们(例如内联函数),而不能在一个单元中编译然后链接到另一个单元的东西因为它们没有完全定义(模板)。模板函数经常在多个编译单元中进行相同的实例化,并且链接器具有特殊的智能来丢弃重复项。
这意味着将接口和实现分离为头文件和正文文件并不是很干净。 Ada有一个更清晰的分离 - 但是更复杂的构建过程来补偿IIRC。 Java简单地删除了用于接口和实现的单独文件。
多年来,连接器已经变得更复杂,并且接管了编译器的一些工作,而且这些天的解释很多都是错误的,但基本模式仍然存在。模板函数和内联函数可以(通常需要)进入标题,以及所有不直接生成对象代码共享声明。正常的函数定义不应该在头文件中。