你有没有写过没有守卫的头球?

时间:2011-10-14 03:26:53

标签: c++ header standards header-files

我想知道为什么C ++编译器不会自动为标头生成标头保护?

// Why do I have to write this for every .hpp file I create?!!
#ifndef myheader_hpp__
#define myheader_hpp__
// ...
#endif

我没有遇到在编写标题时不需要它们的情况。我看不出相反行为的真实用例,但我很高兴看到一个。是技术上的困难还是只是历史?!

4 个答案:

答案 0 :(得分:10)

some preprocessor tricks that require the same header included multiple times into the same compilation unitAnother reference.

除此之外,大多数编译器都允许您将所有这些缩短为:

#pragma once

答案 1 :(得分:2)

对于编译器,自动放入包含警卫并不是真正实用的。您可以为方法/函数/类/等定义原型而不会遇到问题,这通常在头文件中完成。但是,当在头文件中定义类时,如果编译器包含两个不同的.cpp文件或其他头文件,则会遇到编译器多次定义类的问题。

真的,包含守卫只是标头的一招。你不总是需要它们,并且在某些情况下你不会使用它们。这实际上更容易,信不信由你。

答案 2 :(得分:2)

因为它是将一个文件插入另一个文件的通用机制。

只有通用能力才能在99%的情况下用于非常常见的特定目的。

答案 3 :(得分:2)

我只想指出Clang / LLVM项目。

在这个项目中,他们创建了一种使用简单描述性语言对数据进行编码的方法,然后将其提供给一个用于生成C ++文件的工具(称为tblgen for Table Generator)。例如,the diagnostics

let Component = "Sema" in {
let CategoryName = "Semantic Issue" in {

// Constant expressions
def err_expr_not_ice : Error<
  "expression is not an integer constant expression">;

....

Clang中有几千个诊断程序,分成几个文件。一旦由tblgen处理,它们将生成一个巨大的.inc文件,对于每个诊断,它将包含一个宏调用。通过定义宏并包含文件,您可以生成C++ table(或其他任何其他内容,但通常用于表):

static const StaticDiagInfoRec StaticDiagInfo[] = {
#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,               \
             SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,              \
             CATEGORY,BRIEF,FULL)                                 \
  { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS,           \
    NOWERROR, SHOWINSYSHEADER, CATEGORY,                          \
    STR_SIZE(#ENUM, uint8_t), STR_SIZE(GROUP, uint8_t),           \
    STR_SIZE(DESC, uint16_t), STR_SIZE(BRIEF, uint16_t),          \
    STR_SIZE(FULL, uint16_t),                                     \
    #ENUM, GROUP, DESC, BRIEF, FULL },
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticDriverKinds.inc"
#include "clang/Basic/DiagnosticFrontendKinds.inc"
#include "clang/Basic/DiagnosticLexKinds.inc"
#include "clang/Basic/DiagnosticParseKinds.inc"
#include "clang/Basic/DiagnosticASTKinds.inc"
#include "clang/Basic/DiagnosticSemaKinds.inc"
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#undef DIAG
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};

相同的文件可以生成不同的表,因为您可以随意编写宏。

当然,这是一个非常具体的用途。

但不要担心,即使模块没有进入C ++ 11,我们也希望C ++ 1x。