【问题标题】:What is the function of include guard in .cpp (not in .h)? [duplicate].cpp(不在.h)中包含保护的功能是什么? [复制]
【发布时间】:2015-08-04 00:05:12
【问题描述】:

好的,可能这个问题已经有了答案,但我不知道要搜索什么关键字(我的大部分搜索结果都是关于仅在.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

,这个包含守卫的作用是什么?

【问题讨论】:

标签: c++


【解决方案1】:

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

说你有

啊哈:

#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 文件中也建议使用包含保护。

【讨论】:

  • 请注意,一些现代编译器(例如 GCC)会记住标头保护,这使得这种技术变得多余。
【解决方案2】:

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

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

但在现代系统上,这个技巧不是必需的。尽管除了重复代码并增加混乱之外,这不会造成任何伤害,但这会起作用。建议在包含文件中添加哈希保护。

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

新风格:

/* 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

【讨论】:

  • 是的,这是打开文件的成本。
  • 但似乎根本不需要 B.h 和 C.h 吗?恕我直言,他们应该被删除
  • @tejashs 抱歉,我无法理解您的担忧。能否请您详细说明。 b.hc.h 是独立的文件,就像 a.h 一样,可能完全正交。
  • 如果我们知道 b.h 和 c.h 包含在 a.h 中,我们根本不需要将它们包含在 cpp 文件中。只有 a.h 就足够了
  • @tejashs 你怎么知道b.hc.h 包含在a.h 中?我可能错过了。它是在某处写有问题还是暗示?我再次阅读了这个问题,但没有运气。
【解决方案3】:

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

A.h 可能看起来像这样

#define __A__
#include B.h

如果没有守卫,B.h 将被包含两次,这可能会导致错误。因此,cpp 中的#ifndef 行只是保护自己免受包括其他标头在内的标头的影响。

【讨论】:

    猜你喜欢
    • 2022-11-27
    • 2011-02-04
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 2013-05-25
    • 2012-10-19
    • 1970-01-01
    相关资源
    最近更新 更多