何时在一个文件中多次包含相同的标题是有用的?

我正在阅读一个文件中相同标题的多个包含,并找到一个有趣的声明( 链接 ):

如果您有意多次包含头文件,那么有两个带头文件的技巧(这实际上提供了一个有用的function)。

据我所知,这些技巧可能在实际项目中不受欢迎和困惑(特别是因为人们会采取预防措施来防范多种内容,例如包括警卫和#pragma once )。 但是,那些技巧是什么? 我提出了一些想法,但希望看到一些实际的例子(理想情况下,安全和尝试)。

我的想法:

  • C中的伪模板,其中模板参数被预处理器定义替换。 它可以在没有包含的情况下完成,但function可能太大或太多,因此制作单独的文件是有意义的。
  • 逐块结构/类构造(连接片段)。 在使用公共成员定义结构时,它可以帮助模拟C中的inheritance并防止代码重复。
  • 查找表和其他编译时数据结构(同样,借助预处理器定义)。

#include "file"表示获取头文件并放入其所有内容而不是#include行。

我们通常使用标头来定义类型,并为源文件添加前向声明。 在文件中定义两次相同类型(循环包含将始终导致它)会产生编译错误,因此我们使用#ifndef#pragma once 。 (或两者)

但我们也可以放置重复的代码和宏,并将其包括几次,即使在同一个文件中也是如此。 在这种情况下,我们不会使用#ifndef#pragma once 。 如果你这样做,你必须格外小心,只有当你知道自己在做什么时才这样做。

例如:如果在某些操作系统中调用特定的系统函数(或者甚至是ac宏,如: offsetof )会导致一堆警告,而且它会让您感到困扰,并且您确定您的代码是好的,但您不想禁用所有你在所有项目或文件上得到的警告,你只想在调用特定function时禁用它。

 //suppress the warnings: #if defined(__GNUC__) #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wreorder" #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #pragma GCC diagnostic ignored "-Wsequence-point" #endif #endif // __GNUC__ //here you call the function... func(x,y,z); //unsupress: bring back the warnings to normal state #if defined(__GNUC__) #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) #pragma GCC diagnostic pop #endif #endif // __GNUC__ 

这将使您的代码看起来非常脏,特别是如果您多次调用该函数。

一种可能的解决方案,(我不是建议它是最好的……)是制作2个标题,一个用于抑制警告,另一个用于取消抑制。

在这种情况下,您的代码可能如下所示:

 #include "suppress.h" func(x,y,z); #include "unsuppress.h" //.... more code come here //now when call it again: #include "suppress.h" func(x,y,z); #include "unsuppress.h" 

“标准”示例是标头。 包含它的效果取决于NDEBUG的值:

 #include  void func1(void) { assert(...); } #undef NDEBUG #include  void func2(void) { assert(...); } #define NDEBUG #include  void func3(void) { assert(...); } 

func1()的断言处于活动状态,除非编译环境中的某些内容在包含时设置了NDEBUGfunc2()的断言处于活动状态,因为当包含时, NDEBUG未定义。 func3()的断言处于非活动状态,因为在包含时定义了NDEBUG

话虽如此,我从未在现实生活中使用过此设施,但C标准祝福(强制要求)所显示的行为。

请注意,这不是偶然发生的; 之所以会发生这种情况,是因为标头经过精心设计,可以在一个TU中重复使用多次。