将include
部分中的自定义标题放在比标准标题更高的位置是否合理?
例如,包括someclass.hpp
中的部分:
#include "someclass.h"
#include "global.h"
#include <iostream>
#include <string>
这是最佳做法吗?如果是,它的利润是多少?
答案 0 :(得分:7)
将#include "widget.h"
作为widget.cpp
中的第一件事是相当普遍的做法。这样做可以确保widget.h
是自包含的,即不会无意中依赖其他头文件。
除此之外,我认为这基本上是个人偏好的问题。
答案 1 :(得分:6)
原因是如果您忘记在someclass.h
中包含依赖标头,那么无论实现文件将其包含为第一个标头,都会收到未定义或未声明类型的警告/错误,以及诸如此类的错误。如果首先包含其他标题,那么您可能会掩盖这一事实 - 假设包含的标题定义了所需的类型,函数等。示例:
my_type.h:
// Supressed include guards, etc
typedef float my_type;
someclass.h:
// Supressed include guards, etc
class SomeClass {
public:
my_type value;
};
someclass.cpp:
#include "my_type.h" // Contains definition for my_type.
#include "someclass.h" // Will compile because my_type is defined.
...
这将编译好。但是想象一下你想在你的程序中使用SomeClass
。如果在包含my_type.h
之前未包含someclass.h
,则会收到编译错误,指出my_type
未定义。例如:
#include "someclass.h"
int main() {
SomeClass obj;
obj.value = 1.0;
}
答案 2 :(得分:3)
在深入研究具体细节之前,有两个重要的观察结果:
因此,答案取决于您是否进行了单元测试。
一般的经验法则是包括以标准库开头的标题,然后是第三方标题(包括开源项目),然后是您自己的中间件,实用程序等......最后是本库的本地标题。它或多或少遵循依赖顺序以符合观察2 。
我见过的唯一例外是与当前源文件对应的 one 标头,首先将其包括在内以确保它是自包含的(观察1 )...但这只有在你没有单元测试时才有效,因为如果你这样做,那么单元测试源文件是一个非常好的检查位置。
答案 3 :(得分:1)
从系统标题开始。
如果标题之间没有依赖关系,则两种方式都有效,但由于编程本质上是通信,不是计算机而是与其他人通信,因此使其合乎逻辑且易于理解非常重要。我的观点是,最好从系统头开始。
我基于我的第一个编程课程(1984年,我认为),我们在Lisp编程,并被教导如下思考:你从正常的Lisp语言开始,然后你创建一个新的语言,通过添加一些函数和数据类型,对您的应用程序更有用。例如,如果您添加日期和操作日期的功能,则可以将此新语言称为Lisp-with-dates。然后你可以使用Lisp-with-dates来创建一个具有日历功能的新语言,可以称之为Lisp-with-calendars。像洋葱中的层。
类似地,您可以将C视为具有“核心”语言,没有任何标题,然后您可以通过#including stdio.h将此语言扩展为具有I / O功能的新的更大语言。您可以通过#including more headers向核心语言添加越来越多的东西。 (我知道其他上下文中的术语“C语言”是指整个标准,带有所有标准标题,但在这里请耐心等待。)每个新的#included标题创建一个新的,更大的语言,以及一个额外的层洋葱。
现在,对我来说,似乎标准标题显然应该是这个洋葱的内部部分,因此在自定义标题之前。您可以通过向C-with-I / O添加内容来创建C-with-monsters语言,但是创建C-with-I / O的人并不是以C-with-monsters开头。
答案 4 :(得分:1)
虽然这只是个人选择,但我希望首先包含标准标题。几个原因:
#ifdef..#define
都会被正确映射,而不是标准的标题错误解释它们。这适用于条件编译以及某些宏的值,而正在编译标准头文件。答案 5 :(得分:0)
您包含c ++编译器的任何地方都将其视为相同的