自定义标题高于标准?

时间:2012-02-21 07:51:20

标签: c++ header

include部分中的自定义标题放在比标准标题更高的位置是否合理? 例如,包括someclass.hpp中的部分:

#include "someclass.h"
#include "global.h"

#include <iostream>
#include <string>

这是最佳做法吗?如果是,它的利润是多少?

6 个答案:

答案 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)

在深入研究具体细节之前,有两个重要的观察结果:

  1. 开发新的标头/源对时,检查标头是否为自包含非常重要。为此,最简单的方法是首先包含在文件中。
  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 ++编译器的任何地方都将其视为相同的