在.cpp(不是.h)中包含guard的功能是什么?

时间:2015-05-22 05:02:28

标签: c++

好的,可能这个问题已经有了答案,但我不知道要搜索哪个关键字(我的搜索结果大部分仅包括.h中的警卫,而不是.cpp

有时我在cpp中看到每个#include行都有一个额外的包含守卫(有时甚至包含.h已经拥有自己的包含守卫),如下所示: SomeClass.cpp

#ifndef__A__
#include A.h
#endif
#ifndef__B__
#include B.h
#endif
#ifndef__C__
#include C.h
#endif

而不是

SomeClass.cpp

#include A.h
#include B.h
#include C.h

,这包括后卫的功能是什么?

3 个答案:

答案 0 :(得分:2)

John Lakos在他的书Large-Scale C++ Software Design中推荐了在.cpp文件中使用包含警卫的做法。我不知道他之前是否有人推荐过这种做法。

说你有

A.H:

#ifndef __A__
#define __A__

#include "B.h"
#include "C.h"

// ...
// ...
// ...

#endif

B.h:

#ifndef __B__
#define __B__

// ...
// ...
// ...

#endif

C.h:

#ifndef __C__
#define __C__

// ...
// ...
// ...

#endif

SomeClass.cpp:

#ifndef __A__
#include "A.h"
#endif

#ifndef __B__
#include "B.h"
#endif

#ifndef __C__
#include "C.h"
#endif

编译SomeClass.cpp时,包含A.h的内容。作为包含A.h内容的副产品,还包括B.h和C.h的内容。此外,还定义了预处理器宏__A____B____C__。当行

#ifndef __B__
处理

,因为已经定义了__B__,所以跳过下一行。

如果SomeClass.cpp只有:

#include "A.h"
#include "B.h"
#include "C.h"

必须打开并处理文件B.h.由于包含防护,文件的内容不会再包含在内,但必须打开和关闭文件。

通过使用第一个策略,您可以避免打开和关闭B.h和C.h.对于大型C ++项目,John Lakos断言,成本太高了。因此,即使在.cpp文件中,使用包含保护的建议。

答案 1 :(得分:1)

这意味着如果文件已经包含(symbol_specific_to_header已定义),甚至不检查头文件的内容。

在古代打开文件并且检查内容是否已经包含在标题本身是昂贵的(打开,阅读和关闭标题的成本非常高)这个技巧被用来减少编译时间。

但是在现代系统上,不需要这个技巧。虽然这不会造成任何伤害,除了代码重复并添加混乱,这将起作用。建议在包含文件中添加hashguards。

这是头文件的外观和包含方式。

新风格:

/* A.h */
#pragma once
...

/* A.h */
#ifndef A_H
#define A_H
...
#endif

用法:

#include "A.h"

或者使用预编译的标头。

旧式

你提到的古老风格:

/* A.h */
#define A_H
...

用法:

#ifndef A_H
#include "A.h"
#endif

答案 2 :(得分:0)

这是为了防止包含相同的标题两次。

A.h可能看起来像这样

#define __A__
#include B.h

没有守卫,B.h将被包括两次,这可能会导致错误。因此,cpp中的#ifndef行只是保护自己免受包括其他标题在内的标题的攻击。<​​/ p>