3

我想知道是否有一些赞成和反对直接在包含文件中包含语句而不是在源文件中包含它们。

就我个人而言,我喜欢让我的包含“干净”,所以当我将它们包含在一些 c/cpp 文件中时,我不必寻找所有可能的头文件,因为包含文件本身并不处理它。另一方面,如果我在包含文件中有包含,编译时间可能会变长,因为即使有包含保护,也必须首先解析文件。这只是口味问题,还是有任何优点/缺点?

我的意思是:

样本.h

#ifdef ...

#include "my_needed_file.h"
#include ...

class myclass
{
}

#endif

样本.c

#include "sample.h"

my code goes here

相对:

样本.h

#ifdef ...

class myclass
{
}

#endif

样本.c

#include "my_needed_file.h"
#include ...
#include "sample.h"

my code goes here
4

6 回答 6

7

实际上没有任何标准的最佳实践,但对于大多数帐户,您应该在标题中包含您真正需要的内容,并提前声明您可以做的事情。

如果实现文件需要标头明确不需要的东西,那么该实现文件应该包含它本身。

于 2013-05-16T08:01:11.887 回答
3

该语言没有任何要求,但几乎普遍接受的编码规则是所有标题必须是自给自足的;由包括包含在内的单个语句组成的源文件应该编译没有错误。验证这一点的常用方法是让实现文件在其他任何内容之前包含其标题。

并且编译器只需要读取每个包含一次。 如果它可以确定它已经读取了文件,并且在读取它时检测到包含保护模式,则不需要重新读取文件;它只是检查控制预处理器令牌是否(仍然)定义。(有些配置编译器无法检测包含的文件是否与之前的包含文件相同。在这种情况下,它确实必须再次读取文件并重新解析它。这种情况相当罕见,但是.)

于 2013-05-16T08:31:07.183 回答
2

头文件应该被视为 API。假设您正在为客户端编写一个库,您将为他们提供一个用于包含在其代码中的头文件,以及一个用于链接的编译二进制库。

在这种情况下,在你的头文件中添加一个'#include'指令会给你的客户和你带来很多问题,因为现在你必须提供不必要的头文件来编译东西。尽可能多地前向声明可以使 API 更简洁。它还使您的客户能够根据需要在您的标头上实现自己的功能。

如果您确定您的标头永远不会在当前项目之外使用,那么任何一种方式都不是问题。如果您使用包含防护,编译时间也不是问题,无论如何您都应该使用它。

于 2013-05-16T08:06:21.913 回答
1

在标头中有更多(不需要的)包含意味着在接口级别有更多数量的(不需要的)符号可见。这可能会造成大量破坏,可能导致符号冲突和界面臃肿

于 2013-05-16T08:13:12.097 回答
1

另一方面,如果我在包含文件中有包含,编译时间可能会变长,因为即使使用包含保护

如果您的编译器不记得哪些文件包含保护并且避免重新打开和重新标记文件,那么请使用更好的编译器。大多数现代编译器已经这样做了很多年,因此多次包含同一个文件是没有成本的(只要它包含保护)。参见例如http://gcc.gnu.org/onlinedocs/cpp/Once_002dOnly-Headers.html

标题应该是自给自足的,并包含/声明他们需要什么。期望您的标头的用户包含其依赖项是不好的做法,也是让用户讨厌您的好方法。

如果之前my_needed_file.h需要(因为需要它的声明/定义),那么它应该包含在 中,毫无疑问。如果不需要它并且只需要它,那么只在其中包含它,我的偏好是在之后包含它,这样如果缺少它需要的任何标题,那么你会更快地知道它: sample.hsample.hsample.hsample.hsample.c sample.hsample.h

// sample.c
#include "sample.h"
#include "my_needed_file.h"
#include ...
#include <std_header>
// ...

如果您使用此#include命令,那么它会迫使您sample.h自给自足,从而确保您不会给标题的其他用户带来问题和烦恼。

于 2013-05-16T08:26:44.320 回答
-1

我认为第二种方法更好,只是因为以下原因。

  1. 当您的头文件中有函数模板时。

    class myclass
    {
        template<class T>
        void method(T& a)
        {
           ...
        }
    }
    

而且您不想在 myclass.cxx 的源文件中使用它。但是您想在 xyz.cxx 中使用它,如果您采用第一种方法,那么您最终将包含 myclass.cxx 所需的所有文件,这对 xyz.cxx 没有用。

这就是我现在想到的所有区别。所以我想说应该采用第二种方法,因为它使您的代码在将来都可以维护。

于 2013-05-16T08:48:42.590 回答