使用C ++头文件(.h)与头文件加上实现(.h + .cpp),有哪些缺点?

时间:2010-11-10 15:18:24

标签: c++ header conventions

作为新手C ++程序员,我总是将我的类接口放在.h文件中,并在.cpp文件中实现。但是我最近尝试了C#一段时间,我真的很喜欢它的清晰语法和组织文件的方式,特别是在标题和实现之间没有任何关系,你通常为每个.cs文件实现一个类而你不要需要标题。

我知道在C ++中这也是可能的(您可以在.h文件中编写“内联”函数),但到目前为止,我始终看到.h和{{1}之间的明显区别C ++项目中的文件。这种方法有哪些优点和缺点?

谢谢

9 个答案:

答案 0 :(得分:9)

有几种方法可以将C ++中的两个帮助分开。首先,如果您想在不更改接口的情况下更新库,那么在C ++文件中使用代码意味着您只需更新库而不是库和标题。其次它隐藏了实施。也就是说,它强迫人们只根据界面来看你的类,如果代码编写得很好,就应该关注它们。最后,这种分离带来了界面+文档的一种审美清洁。这是你必须习惯的东西,但过了一段时间它会感觉很自然(意见。)

答案 1 :(得分:5)

不要忘记构建时间。

将实现代码放在头文件中会使它们更容易被更改。更改头文件将导致重建包含它们的所有CPP文件,从而增加构建时间。这在大型项目中可能很重要。

我也是保持对我的库用户隐藏实现的粉丝。不幸的是,这不适用于模板类。

我的经验法则:在.H文件中保留声明,将定义保存在.CPP文件中。

答案 2 :(得分:2)

对于你想要用已编译的二进制文件复合C ++的情况(通常在使用库时),在一个地方定义符号会更酷。想象一下,您需要为二进制文件中的全局内容定义外部符号。如果你在同一个文件中有.cpp和.h代码,则必须为每个这样的文件定义二进制文件的符号。以两种文件的方式,您可以只使用一个.h来定义二进制文件和许多使用它的.cpp文件。

答案 3 :(得分:1)

主要区别在于.h文件中实现的内容将放置在包含该标头的每个编译单元中,这将在最终二进制可执行文件中的编译阶段期间创建冗余 ..与.h.cpp分割时,会将其编译在一个目标文件中,该文件稍后通过只有一个编译的二进制代码实现该头文件而与其他对象文件链接。

此外,如果您在.h内声明内容,则无法在更多其他.cpp文件之间共享变量和结构。

答案 4 :(得分:1)

值得注意的是,C#似乎最近在某种程度上进入了C / C ++方向,引入了部分类。

这在IDE中的特殊优势在于Visual Studio设计器将修改处理可视控件或数据成员及其布局的类的一部分,而无需担心破坏方法(应用程序逻辑)驻留在一个单独的文件中。

答案 5 :(得分:1)

我会回复@wheaties并添加一些其他项目

  1. 编译更容易(可能只是我),如果你只修改标题(就像在包含它的所有实现文件中一样),我从来没有能够使编译正常工作。我相信Makefile,你必须手动添加依赖项,这对于非常大规模的项目来说是一个真正的痛苦(再次可能只是我)。因此,如果您的代码在实现文件中,那么更改只是意味着重新编译该特定文件 - 当您想要进行快速更改,构建和测试时非常有用。

  2. 让我重新讨论隐藏方面,由于代码的敏感性,大多数情况下你不希望人们知道实现细节,因此只暴露标题和预先构建的库,分离是关键。

  3. 前向声明,巧妙的技巧,如果它没有在头文件中的任何代码中“使用”,而是在实现中,则不需要在头文件中包含类的实现细节文件你可以包括真正的标题和“这一切都很好”(如果你有循环依赖性有帮助 - 为什么你有它们是不同的问题!)

答案 6 :(得分:1)

在最近的一个大型项目中,我想要使用的系统的作者在.h文件中放置了很多代码。将.h文件包含到我自己的源代码中时,它会在我的文件中添加更多依赖项。在包含项目的依赖项之后,我最终得到了typedef冲突。如果他们已经分离了代码并且只在.h文件中放置了声明,那么它就会简单得多。我建议使用posix类型,只将声明放入.h文件中。

答案 7 :(得分:0)

我看到很多回复主张分离,主要是为了构建时间和实现隐藏的好处。两者都是绝对的,但我会反驳反例:Boost

大多数Boost库使用.hpp文件,没有外部链接。原因是,当编译器必须知道调用例程中的参数类型时,在模板的情况下通常需要这样做。因此,如果您想坚持使用“现代”C ++方法来避免模板的类,那么您可能没有选择。

答案 8 :(得分:0)

至于.cs.cpp / .h的比较部分,我认为您需要牢记C#的主要架构师的背景:Anders Hejlsberg。在Delphi中,您也没有标题和模块的区别(忽略此讨论的包含文件)。您只需在单元文件initializationimplementation中包含两个部分。

已经提到其他几点了。