#include 语句应该驻留在哪里?
作为一个回归 C++ 的新手,我正在尝试对 #include 方法进行排序。
我遵循以下示例中详细说明的一组特定准则。到目前为止,这对我来说已经成功了(整个项目不断编译:)),但我担心将来可能会遇到问题,因此我的问题是 - 这是正确的方法吗?还有更好的吗?解释它的底层逻辑是什么?
考虑以下示例:
Father.h
#pragma once
class Father
{
// Some implementation
};
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
#include "Father.h"
#include "ClassB.h"
#include "StructC.h"
// Some implementation
的类
ClassB.h 和 ClassB.cpp
不包含StructC.h
struct StructC {
// Some implementation
};
我遵循以下准则:
- 所有 *.h 均以
#pragma Once
声明 - 如果 ClassA 继承自类 Father,则它必须将其包含在 *.h 和 *.cpp 文件中
- 如果 ClassA 使用 ClassB(并且在类的作用域中声明了一个 ClassB 变量),则它有一个
class ClassB;
ClassA.h 中的声明和 ClassA.cpp 中的#include "ClassB.h"
- 如果 ClassA 使用 StructC(并且在类的作用域中声明了一个 StructC 变量) ),它必须将其包含在 ClassA.h 和 ClassA.cpp 中
- 如果 ClassA 使用 ClassD 或 StructE 但仅在 ClassA.cpp 文件中,那么它应该仅在其中包含它们
这可能是一组笨拙的指南,对基本逻辑,所以我可能会生气...来吧,我正在尝试在这里学习...:)
更新:
- 正如下面一些人所写的,我在示例中遇到了错误 - 仅当 ClassA 具有指向 ClassB 的指针或引用,而不是具有简单的 ClassB 数据时,才可以在 ClassA 中使用 ClassB 的前向声明 -成员。
As a returning newbie to C++, I'm trying to sort the #include methodology.
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
#pragma once
class Father
{
// Some implementation
};
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
#include "Father.h"
#include "ClassB.h"
#include "StructC.h"
// Some implementation
ClassB.h and ClassB.cpp
A class without includes
StructC.h
struct StructC {
// Some implementation
};
I follow these guidelines:
- All *.h are headed by a
#pragma once
declaration - If ClassA inherits from class Father, it must include it in both *.h and *.cpp file
- If ClassA uses ClassB (and has a ClassB variable declared at the class's scope), it has a
class ClassB;
decleration in ClassA.h and an#include "ClassB.h"
in ClassA.cpp - 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
- If ClassA uses ClassD or StructE but only in the ClassA.cpp file, then it should include them only there
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这些是我个人遵循的准则:
ClassA
包含一个ClassB
,因此需要#include "ClassB.h"
。如果 ClassB 类型仅通过指针或引用出现在文件中,则前向引用就足够了ClassA.cpp
中首先包含ClassA.h
,并使用任意顺序对于以下包含(我使用字母顺序排序)关于其他方面:
#pragma
是非标准的,更喜欢 包含防护std::string
出现在您的头文件中,则您已经到#include
These are the guidelines I personally follow :
ClassA
contains aClassB
so a#include "ClassB.h"
is required. Had theClassB
type only appear in the file by pointer or reference, a forward reference would have been sufficientClassA.h
first inClassA.cpp
, and use an arbitrary ordering for the following includes (I'm using alphabetical sort)Regarding other aspects :
#pragma
is non standard, prefer include guardsstd::string
appears in your header file, you have to#include <string>
当 ClassA 具有此类型的数据成员时,不要使用 ClassB 的前向声明。
当它有一个指向 ClassB 的指针时,就可以使用它,如下所示:
Don't use forward declaration of ClassB, when ClassA has a data member of this type.
It's OK to use it, when it has a pointers to ClassB, as in:
#pragma Once
是非标准的(但得到广泛支持),因此您可能/可能不想使用#ifdef
防护来代替。至于您是否需要
#include
任何特定标头,这取决于情况。如果代码只需要前向声明,请务必通过前向声明类型来避免导入。除了模板之外,我认为将长函数定义放在头文件中可能不太漂亮。
话虽如此,我认为
ClassA.h
实际上应该包含ClassB.h
因为ClassA.h
的任何用户(大概是使用ClassB.h
>ClassA)必须有ClassB.h
。好吧,如果它正在做诸如分配之类的事情。#pragma once
is non-standard (but widely supported), so you may/may not want to use#ifdef
guards instead.As for whether you need to
#include
any particular header, it depends. 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 includeClassB.h
because any user ofClassA.h
(presumably to useClassA
) will have to haveClassB.h
. Well, if it is doing anything like allocating it.我从 Python 中得到的一件事(因为这是绝对的要求)是“将其导入(包含)到使用它的模块中”。这将使您在有或没有定义时摆脱麻烦。
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". This will keep you out of trouble when it comes to having or not having the definitions around.
我通常不会使用
pragma Once
因为 pragma 不是标准的。您可能必须将代码移植到未定义的不同编译器,并且必须使用#ifndef ... #define
习惯用法重写每个代码。这是因为我直接使用
#ifndef ... #define
。第二件事:在头文件中使用许多包含并不是一个好主意:我总是尝试最小化它们。如果它们太多,每次更改其中一个的一点点时,您都必须重新编译每个依赖的 .cpp 文件。
如果是这种情况,我采用 Pimpl 习惯用法,您可以在此处<找到描述。 /a> (参见 C++ 示例)。无论如何,如果项目规模不是那么大,我认为你的方法是正确的。
I usually don't use
pragma once
because pragmas are not standad. 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.This is because I go straight with
#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.
If that's the case, I adopt the Pimpl idiom, that you can find described here (see the C++ example). Anyway, if the project's size is not that big, I think that your approach is correct.