作为 C++ 的新手,我正在尝试整理 #include 方法。
我正在遵循我在下面的示例中详细说明的一组特定指南。到目前为止,这对我来说是可行的(整个项目都在编译 :)),但我担心我将来可能会遇到问题,因此我的问题是 - 这是一种正确的方法吗?有更好的吗?解释它的基本逻辑是什么?
考虑以下示例:
父亲.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 变量),它在 ClassA.h 中有一个
class ClassB;
decleration 和一个#include "ClassB.h"
在 ClassA.cpp 中 - 如果 ClassA 使用 StructC(并且在类的范围内声明了一个 StructC 变量),它必须将它包含在 ClassA.h 和 ClassA.cpp 中
- 如果 ClassA 使用 ClassD 或 StructE 但仅在 ClassA.cpp 文件中,那么它应该只在其中包含它们
这可能是一套笨拙的指南,对底层逻辑知之甚少,所以我可能会感到愤怒......来吧,我 尝试在这里学习... :)
更新:
- 正如一些人在下面所写的,我在这个例子中有一个错误——只有当 ClassA 有一个指针或对 ClassB 的引用时,你才能在 ClassA 中使用 ClassB 的前向声明,而如果它有一个简单的 ClassB 数据成员则不能。
最佳答案
这些是我个人遵循的准则:
- 尽可能使用前向声明而不是包含。在你的情况下,
ClassA
包含ClassB
所以#include "ClassB.h"
是必须的。有ClassB
类型仅通过指针或引用出现在文件中,前向引用就足够了 - 使头文件“自给自足”:编译不应该依赖于包含的顺序,并且包含文件应该包含/转发声明所有需要解析的内容
- 为确保遵守上述准则,请始终包含
ClassA.h
第一名ClassA.cpp
,并对以下内容使用任意排序(我使用的是字母排序)
关于其他方面:
-
#pragma
是非标准的,更喜欢include guards - 请记住,永远不要转发声明标准类型:if
std::string
出现在你的头文件中,你有到#include <string>
- 如果您最终得到一个包含一百万个其他文件的头文件,您可能需要查看 pimpl idiom减少依赖性(本文还包含其他一些关于头文件的指南)。
关于c++ - #include 语句应该放在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4274755/