是否存在两次包含相同标题实际上有用的情况?

为我的h / hpp文件创建标题保护对我来说一直是标准做法,但我想知道,为什么甚至可以两次包含相同的文件? 是否存在实际需要不受保护的标头的情况?

“参数化”头文件可用于模拟C中的C ++ – ish样式模板。在这种情况下,头文件将依赖于许多宏(“模板参数”)。 它将根据这些宏的实际“值”生成不同的代码。

因此,此类标头的典型用法看起来是一系列“模板参数”宏定义,后跟#include指令,后跟另一个“模板参数”宏定义序列,后跟相同的#include ,依此类推。

https://stackoverflow.com/a/7186396/187690

使用此技术时,您将看到没有任何包含保护的头文件或包含仅包含文件一部分的包含保护的头文件。

像Boost.PP这样的东西通过多次包含标题来做很多技巧。 它基本上允许原始forms的循环。

此外, X-Macros被设计为多次包含。

在C:

 #undef NDEBUG #include  ...code using active asserts... #define NDEBUG #include  ...code using disabled asserts... 

冲洗并重复。 C ++中的模拟使用头文件

因此,有时候有理由两次包含标题。 不经常,但有理由这样做。

像这样的情况是罕见的,当它们确实存在时,重新设计更适合。 我能想到的是收集声明的标题:

 //functions.h virtual void foo(); virtual void goo(); //classes.h class A : public Base { #include "functions.h" }; class B : public Base { #include "functions.h" }; 

如果functions.h包含警卫,这将无法工作,但话又说回来,这是非常尴尬的代码……

想象一下,您正在为您的微型引擎编写自己的模板数组包装器(元素是指针),其中数组可以是:

  • 动态或静态
  • 索引/订单是否重要
  • 您可以删除数组外部或内部的元素(不只是从数组中删除)

所以,你可以创建一个所有这些处理的类,但它总是会检查我们能做什么或不能做什么。 最好的是创建单独的类,但是在这里我们有相同的代码,你可以(如果不小心)在其中一个函数中犯错,再添加一个新函数会更慢。

所以最好是使用“参数化”头文件(如AnT所述)并简单地创建类

  • Cl_Array_Dy,Cl_Array_DyIn,Cl_Array_DyDel,Cl_Array_DyInDel
  • Cl_Array_St,Cl_Array_StIn,Cl_Array_StDel,Cl_Array_StInDel

代码示例:

// TestDfM.h

 #ifndef TEST_DFM_H # define TEST_DFM_H // first we need to make sure neither of these is defined # ifdef Df_ARG1 # undef Df_ARG1 # endif # ifdef Cl_First # undef Cl_First # endif # ifdef Cl_Second # undef Cl_Second # endif # ifdef Df_FIRST # undef Df_FIRST # endif # ifdef Df_SECOND # undef Df_SECOND # endif # ifdef TEST_DF_H # undef TEST_DF_H # endif // we need this # define Df_FIRST 1 # define Df_SECOND 2 // first class creation # define Df_CLASS Df_FIRST # define Df_ARRAY Cl_First # include "TestDf.h" // cleanup (after 1st) # undef Df_CLASS # undef Df_ARRAY // second class creation # define Df_CLASS Df_SECOND # define Df_ARRAY Cl_Second # define Df_ARG1 # include "TestDf.h" // cleanup (after 2st) # undef Df_CLASS # undef Df_ARRAY # undef Df_ARG1 // so we theoretically cannot include TestDf.h anymore (anywhere) # define TEST_DF_H #endif // TEST_DFM_H 

// TestDf.h

 // nothing to do here if the main header for this was not included // also we should only call this inside the main header #if defined(TEST_DFM_H) && !defined(TEST_DF_H) # include "../Includes.h" class Df_ARRAY { public: int m_shared; # ifndef Df_ARG1 Df_ARRAY(int in_shared=0) { m_shared= in_shared; } void f_info() { printf("out: %d\n", m_shared); } # else int m_x; Df_ARRAY(int in_shared=0, int in_x= 7) { m_shared= in_shared; m_x= in_x; } void f_info() { printf("out: %d [also has %d]\n", m_shared, m_x); } # endif # if Df_CLASS == Df_FIRST void f_class() { printf("1st\n"); } # elif Df_CLASS == Df_SECOND void f_class() { printf("2nd\n"); } # endif }; #endif // TEST_DFM_H 

// Main.cpp

 #include "Array/TestDfM.h" int main(int argc, char** argv) { Cl_First a(6); Cl_Second b(2); a.f_class(); // 1st b.f_class(); // 2nd a.f_info(); // out: 6 b.f_info(); // out: 2 [also has 7] return 0; } 

只要遇到头文件,就会以文本方式包含它们。 没有任何真正的理由说明为什么它们不能被包括在一次以上。 如果标题仅用于声明而没有定义(并且没有使用默认参数的模板声明),那么将它们包含多次不会有任何问题。

那就是说是不止一次包含文件的典型示例:您可以更改NDEBUG的定义,并在一个转换单元中从assert()宏获取不同的行为。

现在有一些像include_once这样的东西只包含一个文件,结果certificate并不像人们想象的那样微不足道。 这是一个例子,不清楚应该包括foo.h频率:

 #include_once "foo.h" #include_once "./foo.h" #include_once "bar/foo.h" 

假设include_once包含一次文件, foo.h应该多久包括一次? 所有三个文件都可以轻松引用相同的物理文件,但这可能不容易看到,例如,因为一个是另一个文件的链接。 似乎最好将控制权交给程序员如何控制它们最终被使用的频率。