我在什么顺序包含头文件?

时间:2011-04-05 22:42:07

标签: c++ class header include precompiled

我是编程新手,头文件的主题在我开始使用它们之后会让我失望。除此之外,我正在尝试使用预编译的头文件。我也在使用SFML库,因此我必须包含那些标题。

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

如果

,我将在所有文件中包含标题的顺序
  • 所有类都包含SFML类的实例
  • D类包含A类和C类
  • 的实例
  • C类包含B类的实例 我的代码:(注意:所有标题都有标题保护)

stdafx.h中:

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

A.H

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

A.cpp

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

B.h

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

B.cpp

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

C.h

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

};

C.cpp

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

D.h

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

D.cpp

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

的main.cpp

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

5 个答案:

答案 0 :(得分:9)

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

为了非正式地测试你记得在头文件中包含正确的标题,* .cpp文件应该#include应该有效的最小头文件集。因此,如果ABCD有单独的头文件,并且您的cpp文件使用类D,那么它应该只包括的迪拉姆即可。不会产生编译器错误,因为 Dh #include s Ah Ch Ch 包括 Bh Ah Bh​​ 包含SFML标头(无论是什么)。如果看起来合适, Ch Dh 可以包含SFML标题,但如果可以确定依赖项( Bh​​ ),则不是必需的。并且)已经包含了它。

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

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

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

答案 1 :(得分:1)

查看a similar question以了解编写标题的好方法。

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

答案 2 :(得分:1)

A.h应该包括SFML

A.cpp应包括A.h

D.h应该包括SFML,A.h和C.h

D.cpp应该包括D.h

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

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

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

所有头文件都应该有多个包含警卫。

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

完成此操作后,不再重要您在每个文件中包含标题的顺序。所以你可以做你喜欢的事情,但我建议Google's C++ style guide关于这个主题(点击箭头的东西),调整为stdafx.h的帐户。

答案 3 :(得分:1)

C 继承了 B 类。因此,它应该看到标识符B。所以,请在此处加B.h -

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

};

D 包含类AB的对象。因此,在“D.h”本身中包含A, B的标题。

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

<强> D.cpp

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

请注意,每个标头都需要包含在相应的源文件中。单独考虑每个源文件,并查看源文件中是否先前已定义的内容。

答案 4 :(得分:0)

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