2016-03-01 68 views
4

如果一个库包含在一个类头中,然后这个头包含在另一个类中,那么我是否必须再次包含这个库?#include如何在C++中工作?

例如:

#ifndef A_H 
#define A_H 

#include<someLibrary.h> 

class A{ 
    ... 
} 

#endif 

然后另一个类包括A.H头

#include<A.h> //include class A 
class B{ 
    ... 
} 

我必须包括 “someLibrary.h” B类?

+5

'B'是否使用任何来自''(即直接而不是'A')的东西?如果是这样,那么是的,“包括你使用的东西” - 它使代码库对包含更改更加强大。 – Niall

回答

4

不,#include s为传递。

但是,如果您的第二个文件本身使用someLibrary中的符号,则重新包含标题是一种很好的风格。这样你就不会“希望和祈祷”你永远不会删除中间包括。如果每个源文件#include都直接需要,您的代码库将更加强大。标题警卫防止这成为浪费政策。

+0

因此,如果B类使用someLibrary.h中的某些东西,那么代码仍然可以运行,但这不是好习惯。你是这个意思吗? – tony

+0

@Mahalanobis:是的 –

4

您不包括类或库,您只需包含头文件,并且这是一个文本操作(有点像复制&粘贴由预处理器完成)。

阅读更多关于C/C++ preprocessorGNU cpp

您可以要求编译器向您显示源文件foo.cc的预处理格式,例如,与g++ -Wall -C -E foo.cc(它将在标准输出预处理的形式溢出)

对于一个小项目(例如小于200KLOC)中,作为你的所有翻译单元包含只是一个单一的共同的头文件是明智的(我相信,有许多小的头文件是坏习惯,所以我通常为每个头文件放置多个类定义)。顺便说一句,(单头文件)的方法是友好的precompiled headers。有些人更喜欢在这个单独的头文件中拥有几个他们自己的#include-d副标题。

发现大多数C++标准头文件(如<map><vector> ....)带来大量的文字,所以你不希望有微小的编译单元(我的Linux系统上,#include <vector>是拖一万多因此只有几十条源代码行对编译器而言效率不高)

另请注意,C++类定义通常包含大量内联成员函数(并且您实际上想要给出内联函数的主体在同一个头文件中)。所以C++头代码往往是相当大的......

(有些人喜欢打破一个头文件中的许多子报头,它们总是包含在一起)

+2

_“对于小型项目(例如小于200KLOC),所有翻译单元只包含一个共同的头文件是明智的”_O.O –

+1

@PreferenceBean:您的“o.O”意味着什么? –

+1

这是两只眼睛和一个非常小的鼻子,在“rreeeeaaalllyy ????”配置 –

4

preprocessor#include指令确实如其名所示,它实际上是包含指令位置处的文件。

简单的例子:假设我们有文件,第一头文件名为a.h

// Our class 
class A 
{ 
    // Stuff for the class 
}; 
// End of the class 

然后源文件a.cpp

// Include header file 
#include "a.h" 
// Header file included 

int main() 
{ 
    // Code 
} 

预处理器生成文件看起来像

// Include header file 
// Our class 
class A 
{ 
    // Stuff for the class 
}; 
// End of the class 
// Header file included 

int main() 
{ 
    // Code 
} 

这个包含是递归的,所以如果头文件包含另一个头文件,那么其他头文件也将被包含。

由预处理器生成的源文件称为translation unit,它是编译器实际看到的内容。


以上是在现代预处理器是如何工作的简单化,虽然它可以单独运行,以创建一个预处理的源文件,这是比较常见的预处理器是编译器简化分析过程的一部分。


您还应该注意您使用的术语不正确。一个库可以(通常是)具有一个或多个头文件,这些头文件在编译源代码时使用。然后一个库经常(但不总是)包含一个特殊的库文件链接与编译器创建的目标文件。

一个没有链接库的库叫做头只有库。