C++;预编译的头文件和包含的文件组织 我有一个非常大的本地C++项目,每个项目都有自己定义的.CPP和.h文件。没什么奇怪的。我在预编译的头文件stdafx.h中声明了所有类,并且还包括在stdafx.h文件中,如下所示(以允许Foo引用Bar和Bar引用Foo)

C++;预编译的头文件和包含的文件组织 我有一个非常大的本地C++项目,每个项目都有自己定义的.CPP和.h文件。没什么奇怪的。我在预编译的头文件stdafx.h中声明了所有类,并且还包括在stdafx.h文件中,如下所示(以允许Foo引用Bar和Bar引用Foo),c++,c++11,visual-studio-2013,native,C++,C++11,Visual Studio 2013,Native,这个组织是坏习惯吗 本质上,所有类都声明并包含在每个对象中。我假设编译器不会通过包含编译特定.cpp对象文件所不需要的内容来生成开销二进制文件。到目前为止,我对编译时间也没有任何问题。我只是想知道这是否是一个糟糕的代码组织 我喜欢这种布局,因为stdafx.h文件本质上是一个代码映射,因为所有类都在那里声明,它揭示了嵌套的名称空间是一种易于阅读的格式。这还意味着,我的单个class.h文件不需要几个include语句,这意味着在更改文件名或目录时,需要维护的代码更少 stdafx.h: #pra

这个组织是坏习惯吗

本质上,所有类都声明并包含在每个对象中。我假设编译器不会通过包含编译特定.cpp对象文件所不需要的内容来生成开销二进制文件。到目前为止,我对编译时间也没有任何问题。我只是想知道这是否是一个糟糕的代码组织

我喜欢这种布局,因为stdafx.h文件本质上是一个代码映射,因为所有类都在那里声明,它揭示了嵌套的名称空间是一种易于阅读的格式。这还意味着,我的单个class.h文件不需要几个include语句,这意味着在更改文件名或目录时,需要维护的代码更少

stdafx.h:

#pragma once
namespace MyProject
{
    class Foo;
    class Bar;
}

#include "Foo.h"
#include "Bar.h"
foo.h:

#pragma once

namespace MyProject
{
    class Foo
    {
        // Declare class members, methods, etc
    }
}
foo.cpp:

#include "stdafx.h"

namespace MyProject
{
    class Foo
    {
        // Define class members, methods, etc
    }
}

在我看来,这里有4个关键因素:

  • 编译时:请记住,
    #include“x.h”
    会在该行将所有代码嵌入x.h中。如果项目将大幅增长,请注意您将如何影响未来的编译时间
  • Foo
    Bar
    稳定性:如果
    Foo
    Bar
    正在更改,则必须继续重新编译stdafx.h
  • 循环定义:您将无法再使用正向声明中断循环定义
  • 显式依赖:您将无法查看您的include并知道在特定文件中使用了什么
  • 如果你觉得你的优点超过了这里列出的缺点,那么你所做的一切都是合法的,去做吧

  • 页眉应包含所需的所有内容,不多不少。
    这是易于使用和简单封装的基本要求

    你的例子显然不符合这一点

    要检测冲突,请始终在翻译单元中首先包含相应的标题。
    如果您使用预编译的头文件,这会稍微修改,在这种情况下,必须首先包含它们

  • 预编译的头文件应该只包含很少变化的元素

    对预编译头或其依赖项的任何更改都将强制重新编译所有内容,这与使用一个头完全背道而驰

    你的例子也不符合这一点


  • 总而言之,还有很多需要改进的地方。

    不,它只是无法编译。您可能忘记了包含警卫了吗?但是现在您必须在每次添加或删除类时更新stdafx.h(这意味着重新编译整个项目),至少你的一些类不会在一个项目的stdafx的上下文之外编译,因为它们不会向前声明它们需要的东西。啊,在每个头上添加一次
    #pragma
    。是的,这是一个糟糕的组织。预编译头用于加快编译时间。您必须至少进行一次餐巾纸背面的计算,其中标题很少更改,并且只包括这些标题。只需将所有内容都包含在预编译头中,就可以获得0的性能。困扰我的是
    stdafx.h
    包含
    Foo.h
    ,以及
    Foo.h
    包含
    stdafx.h
    。我觉得那不太好。(据我所知,
    stdafx.h
    不应包含在其他标题中;只能包含在源文件中。)为了澄清,外部依赖项包含在单个.cpp文件中,以跟踪每个类中的包含项。预编译标头中只有内部包含或始终使用的包含。1。此时编译时间不是问题。stdafx.cpp大约需要5秒,其余的.cpp文件总共需要大约5秒。这里没问题,因为我没有包括太多的外部。2.如前所述,我目前不关心必须重新编译stdafx.h,因为它很快。3.循环定义是必须的。有没有更好的方法来做我正在做的事情?4.外部依赖项包含在每个.cpp文件中。@RussellTrahan在2上的评论我同意,为什么预编译的头文件会这样做?此时,您可以使用所有标题,并消除一些复杂性。就3而言,这意味着您的include必须放在您的实现文件中,而不是头文件中。如果所有的头文件都在stdafx.h中,则无法实现这一点。有关更多信息,请参阅本文:我同意我可能正在利用预编译的头,但事实是,我的许多更改都是在定义中,而不是在声明中。在大多数重新编译事件中,我并没有重新编译stdafx.h。我可以使用我不知道的强制包含功能,但我不确定这会给我带来什么好处。另外,我想所有的评论者都没有意识到循环引用确实像我写的那样有效(Foo-CAN参考条)。无论如何,我将此标记为答案,因为我收集到的是,这里的代码可能是非正统的,但在运行时不会招致任何惩罚,这是我在原始问题中提出的问题的一部分。就我个人而言,我认为像这样将一个文件作为一个代码映射,比在编译时进行可能但不太可能的更改(基于我编辑这个项目的方式)更有益。因此,一个短stdafx.h文件真的比消除散布在我的项目中的数百条include语句更重要吗。我想这消除了大多数内部的#include引用。编译stdafx.cpp大约需要5秒钟——这没问题。如果你这样做,为什么不把所有内容都包含在一个大的“monster.cpp”(头文件和源文件)中,然后编译它呢。如果重新编译所有内容都不是问题,那么应该不会太长。。。重要的是