繁体   English   中英

我包含头文件的顺序是什么?

[英]What order do I include header files in?

我是编程新手,在我开始使用很多头文件后,头文件的主题让我陷入困境。 除此之外,我正在尝试使用预编译的头文件。 我也在使用 SFML 库,所以我也必须包含那些头文件。

现在我有 stdafx.h、main.cpp,然后是包含在 Ah、A.cpp、Bh、B.cpp、Ch、C.cpp、Dh 和 D.cpp 中的类 A、B、C 和 D。

如果在所有文件中包含标题,我将采用什么顺序

  • 所有类都包含一个 SFML 类的实例
  • D 类包含 A 类和 C 类的实例
  • C 类包含 B 类的一个实例 我的代码:(注意:所有头文件都有头文件保护)

stdafx.h:

#include <SFML/Graphics.hpp>
#include <iostream>

#include "stdafx.h"
class A
{
    //sfml class
};

A.cpp

#include "stdafx.h"
#include "A.h"

#include "stdafx.h"
class B
{
    //sfml class
};

B.cpp

#include "stdafx.h"
#include "B.h"

通道

#include "B.h"
class C: public B
{

};

cpp

#include "stdafx.h"
#include "C.h"

DH

#include "A.h"
#include "C.h"
class D
{
    A a;
    C C; // if left uncommented I recieve a '1 unresolved externals' error
    //sfml class
}

cpp

#include "stdafx.h"
#include "D.h"

主程序

#include "stdafx.h"
#include "D.h"

我的理念是,在编写良好的代码中,头文件应该包括它们所依赖的所有其他头文件。 我的理由是,不应该包含头文件并因此而得到编译器错误。 因此,每个头文件都应该(在#ifdef#pragma once include guard 之后)包括它所依赖的所有其他头文件。

为了非正式地测试您是否记得在头文件中包含正确的头文件,*.cpp 文件应该#include 应该工作的最小头文件集。 因此,如果ABCD有单独的头文件,并且您的 cpp 文件使用D类,那么它应该只包含Dh 不应导致编译器错误,因为Dh #include s AhChCh包括Bh ,而AhBh包括 SFML 标头(无论是什么)。 如果看起来合适, ChDh可以包含 SFML 标头,但如果您可以确定依赖项( BhAh )已经包含它,则这不是真的必要。

然而,Visual C++ 执行“预编译头”的方式搞砸了这个逻辑。 要求您将"StdAfx.h"作为第一个头文件包含在内,这导致许多开发人员简单地将整个项目的所有#include放在StdAfx.h 中,而不要在任何其他头文件中使用#include . 我不推荐这个。 或者,他们会将所有外部依赖项放在 StdAfx.h(例如 windows.h、boost 头文件)中,并#include 其他地方的本地依赖项,这样更改单个头文件不一定会导致整个项目重新构建。

按照我编写代码的方式,我的大部分 CPP 文件都包含 StdAfx.h 和相应的 .H 文件。 所以A.cpp包括StdAfx.h和Ah,B.cpp包括StdAfx.h和Bh,依此类推。 放置在 cpp 文件中的唯一其他#include是头文件未公开的“内部”依赖项。 例如,如果类A调用printf() ,那么A.cpp (不是Ah )将#include <stdio.h> ,因为Ah不依赖于stdio.h

如果您遵循这些规则,那么#include头文件的顺序无关紧要(除非您使用预编译头文件:那么预编译头文件首先出现在每个 cpp 文件中,但不需要从头文件中包含)。

查看一个类似的问题以了解编写标题的好方法。

简而言之,您希望在定义保护中定义每个标头,以防止在编译期间多次包含标头。 有了这些,对于每个 .h 和 .cpp 文件,只需包含解析任何声明所需的头文件。 预处理器和编译器将负责其余的工作。

啊应该包括SFML

A.cpp 应该包括啊

Dh 应包括 SFML、Ah 和 Ch

D.cpp 应该包括 Dh

main.cpp 应该包括它直接使用的 A、B、C、D 和 SFML 中的任何一个。

通常在 .cpp 文件中,我包含任何您知道必须由其相应的 .h 包含的头文件,因为它们包含在该 .h 中定义的类的数据成员的定义。 因此,在我的代码中 D.cpp 不会包含 Ah That's just me,不过,您可能更愿意包含它,只是为了提醒您 .cpp 文件(大概)使用它。

这留下了 stdafx - 你需要它的地方取决于它使用的东西。 可能到处都需要它,并且 MSVC 不处理(或处理但丢弃?)源文件中#include "stdafx.h"之前的任何内容,因此它应该是每个 .cpp 文件中的第一件事,并且不会出现在其他任何地方。

所有头文件都应该有多个包含保护。

您可以将 SFML(或您喜欢的任何其他内容)添加到 stdafx.h,在这种情况下,您最好从其他任何地方删除这些包含。

完成此操作后,在每个文件中包含标题的顺序不再重要 所以你可以做你喜欢做的事,但我推荐谷歌关于这个主题的 C++ 风格指南(点击箭头的东西),调整到 stdafx.h。

C继承类B 所以,它应该看到标识符B 所以,在这里包括Bh -

#include "B.h"    // Newly added
// Or you can forward declare class B ; 
class C: public B
{

};

D具有类AB对象。 因此,在“Dh”本身中包含A, B标题。

class D
{
    A a;  // Should see the definition of class A
    C c;  // Should see the definition of class B
    //sfml class
}

cpp

#include "A.h"
#include "C.h"
#include "D.h"  // Notice that A.h and C.h should definitely placed before

请注意,每个标题都需要包含在其相应的源文件中。 独立思考每个源文件,并查看所使用的内容是否在源文件中较早定义。

依赖依赖。 与 C# 和其他类似语言不同,C++ 按照编写的顺序执行操作,因此可能存在问题。 如果您确实对订单有问题,那么它将无法编译。

暂无
暂无

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

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