简体   繁体   English

#include语句应该驻留在哪里?

[英]Where should #include statements reside?

As a returning newbie to C++, I'm trying to sort the #include methodology. 作为C ++的新手,我正在尝试对#include方法进行排序。

I'm following a certain set of guidelines I detail below the following example. 我遵循以下示例中详细说明的一系列指导原则。 So far this has worked out for me (the entire project keeps compiling :) ), but I'm worried I may encounter problems in the future, therefore my questions are - is this a correct methodology? 到目前为止,这已经为我做了(整个项目一直在编译:)),但我担心我将来可能遇到问题,因此我的问题是 - 这是一个正确的方法吗? Is there a better one? 还有更好的吗? What's the underlying logic that explains it? 解释它的基本逻辑是什么?

Consider the following example: 请考虑以下示例:

Father.h Father.h

#pragma once
class Father
{
    // Some implementation
};

ClassA.h ClassA.h

#pragma once
#include "Father.h"
#include "StructC.h"
class ClassB;
class ClassA : public Father
{
    StructC struct_c_obj;
    ClassB class_b_obj;
    // Some implementation
};

ClassA.cpp ClassA.cpp

#include "Father.h"
#include "ClassB.h"
#include "StructC.h"
// Some implementation

ClassB.h and ClassB.cpp ClassB.hClassB.cpp
A class without includes 没有包含的课程

StructC.h StructC.h

struct StructC {
    // Some implementation
};

I follow these guidelines: 我遵循以下准则:

  • All *.h are headed by a #pragma once declaration 所有* .h都以#pragma once声明为首
  • If ClassA inherits from class Father, it must include it in both *.h and *.cpp file 如果ClassA继承自Parent类,则必须将它包含在* .h和* .cpp文件中
  • If ClassA uses ClassB (and has a ClassB variable declared at the class's scope), it has a class ClassB; 如果ClassA使用ClassB(并且在类的范围内声明了ClassB变量),则它具有class ClassB; decleration in ClassA.h and an #include "ClassB.h" in ClassA.cpp ClassA.h中的decleration和ClassA.cpp中的#include "ClassB.h"
  • If ClassA uses StructC (and has a StructC variable declared at the class's scope), it has to include it in both ClassA.h and ClassA.cpp 如果ClassA使用StructC(并且在类的范围内声明了StructC变量),则必须将它包含在ClassA.h和ClassA.cpp中。
  • If ClassA uses ClassD or StructE but only in the ClassA.cpp file, then it should include them only there 如果ClassA使用ClassD或StructE但仅在ClassA.cpp文件中,那么它应该仅包含它们

This is probably a clumsy set of guidelines with little understanding of the underlying logic, so I'm probably going to get some wrath... Bring it on, I am trying to learn here... :) 这可能是一个笨拙的一套与底层逻辑有点了解的准则,所以我可能会得到一些愤怒......来吧, 想在这里学... :)

UPDATES: 更新:

  • As some have written below, I have an error in the example - you can use a forward declaration of ClassB in ClassA only if ClassA has a pointer or a reference to ClassB and not if it has a simple ClassB data-member. 正如一些人在下面写的那样,我在示例中有一个错误 - 只有当ClassA有一个指针或对ClassB的引用时才能在ClassA中使用ClassB的前向声明,如果它有一个简单的ClassB数据成员则不能。

These are the guidelines I personally follow : 以下是我个人遵循的指导原则:

  • Prefer forward declarations instead of includes whenever possible. 优先考虑前瞻性声明而不是包括在内。 In your case, ClassA contains a ClassB so a #include "ClassB.h" is required. 在您的情况下, ClassA包含ClassB因此需要#include "ClassB.h" Had the ClassB type only appear in the file by pointer or reference, a forward reference would have been sufficient 如果ClassB类型仅通过指针或引用出现在文件中,则前向引用就足够了
  • Make header file "self sufficient" : compilation should never depend on the order of inclusions, and an include file should include / forward declare all it needs to be parsed 使头文件“自给自足”:编译永远不应该依赖于包含的顺序,并且包含文件应该包含/ forward声明它需要被解析的所有内容
  • To ensure that the preceding guideline is respected, always include ClassA.h first in ClassA.cpp , and use an arbitrary ordering for the following includes (I'm using alphabetical sort) 为了确保遵守前面的准则,始终首先在ClassA.cpp包含ClassA.h ,并对以下包含使用任意排序(我使用字母排序)

Regarding other aspects : 关于其他方面:

  • #pragma is non standard, prefer include guards #pragma是非标准的,更喜欢包括警卫
  • Keep in mind that you should never forward declare standard types : if std::string appears in your header file, you have to #include <string> 请记住,您永远不应该转发声明标准类型:如果头文件中出现std::string必须#include <string>
  • If you end up with a header file which includes a million other files, you might want to look into the pimpl idiom to reduce dependencies (this article also contains several other guidelines regarding header files). 如果您最终得到一个包含一百万个其他文件的头文件,您可能需要查看pimpl习惯用法以减少依赖关系(本文还包含有关头文件的其他一些指导原则)。

#pragma once is non-standard (but widely supported), so you may/may not want to use #ifdef guards instead. #pragma once是非标准的(但受到广泛支持),因此您可能/可能不想使用#ifdef防护。

As for whether you need to #include any particular header, it depends. 至于你是否需要#include任何特定的头,它取决于。 If the code only requires a forward declaration, by all means avoid the import by just forward declaring the type. 如果代码只需要前向声明,那么通过向前声明类型来避免导入。

And with the exception of template stuff, I think it is probably not-too-pretty to place long function definitions in the header files. 除了模板内容之外,我认为在头文件中放置长函数定义可能并不太好。

Having said that, I think that ClassA.h should actually include ClassB.h because any user of ClassA.h (presumably to use ClassA ) will have to have ClassB.h . 话虽如此,我认为ClassA.h实际上应该包括ClassB.h因为任何用户ClassA.h (大概是为了使用ClassA )必须有ClassB.h Well, if it is doing anything like allocating it. 好吧,如果它正在做分配它的任何事情。

Don't use forward declaration of ClassB, when ClassA has a data member of this type. 当ClassA具有此类型的数据成员时,请勿使用ClassB的前向声明。 It's OK to use it, when it has a pointers to ClassB, as in: 当它有指向ClassB的指针时,可以使用它,如:

#pragma once 
#include "Father.h" 
#include "StructC.h" 
class ClassB; 
class ClassA : public Father 
{ 
    StructC struct_c_obj; 
    ClassB *class_b_obj; 
    // Some implementation 
}; 

One thing I've garnered from Python (because it's an absolute requirement there) is "import (include) it in the modules where you use it". 我从Python中获得的一件事(因为它是绝对的要求)是“在你使用它的模块中导入(包括)它”。 This will keep you out of trouble when it comes to having or not having the definitions around. 这将使您在拥有或不具有定义时避免麻烦。

I usually don't use pragma once because pragmas are not standad. 我通常不会使用pragma once因为pragma不是标准的。 You could have to port your code to a different compiler where it's not defined, and you'd have to rewrite each with #ifndef ... #define idiom. 您可能必须将代码移植到未定义的其他编译器,并且您必须使用#ifndef ... #define idiom重写每个编译器。

This is because I go straight with #ifndef ... #define . 这是因为我直接使用#ifndef ... #define

Second thing: using many includes in an header file is not a good idea: I always try to minimize them. 第二件事:在头文件中使用许多包含不是一个好主意:我总是尽量减少它们。 If you got too much of them, each time you change a little thing in one of them you'll have to recompile each dependent .cpp file. 如果你有太多的东西,每次你改变其中一个小东西时,你将不得不重新编译每个依赖的.cpp文件。

If that's the case, I adopt the Pimpl idiom, that you can find described here (see the C++ example). 如果是这种情况,我采用了Pimpl惯用法,你可以在这里找到(参见C ++示例)。 Anyway, if the project's size is not that big, I think that your approach is correct. 无论如何,如果项目的规模不是那么大,我认为你的方法是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM