我是编程新手,头文件的主题在我开始使用它们之后会让我失望。除此之外,我正在尝试使用预编译的头文件。我也在使用SFML库,因此我必须包含那些标题。
现在我有stdafx.h,main.cpp,然后是Ah,A.cpp,Bh,B.cpp,Ch,C.cpp,Dh和D中包含的类A,B,C和D. CPP。
如果
,我将在所有文件中包含标题的顺序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"
答案 0 :(得分:9)
我的理念是,在编写良好的代码中,头文件应该包含它们所依赖的所有其他头文件。我的理由是,不应该包含头文件并且因为这样做而得到编译器错误。因此,每个标头文件应该(在#ifdef
或#pragma once
include guard之后)包含它所依赖的所有其他标头。
为了非正式地测试你记得在头文件中包含正确的标题,* .cpp文件应该#include应该有效的最小头文件集。因此,如果A
,B
,C
和D
有单独的头文件,并且您的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 包含类A
,B
的对象。因此,在“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 ++按照编写顺序执行操作,因此可能存在问题。如果您的订单确实存在问题,则无法编译。