什么时候在一个文件中多次包含同一个标题有用?

2022-01-25 00:00:00 c include c++ header-files

我正在阅读有关在一个文件中包含多个相同标题的内容,并发现了一个有趣的声明(link):

I was reading about multiple inclusions of the same header in one file, and found an interesting statement (link):

头文件有几个技巧是你故意的多次包含它(这实际上提供了一个有用的功能).

There are a couple of tricks with header files were you deliberately include it multiple times (this does actually provide a useful feature).

我知道这些技巧在实际项目中可能是不受欢迎且令人困惑的(尤其是因为人们对多重包含采取了预防措施,例如 包括警卫和#pragma once).但是,这些技巧是什么?我想出了一些想法,但想看看一些实际的例子(理想情况下,安全和尝试).

I understand that those tricks are probably undesired and confusing in real-world projects (especially since people take precautions against multiple inclusions, like include guards and #pragma once). But still, what are those tricks? I came up with a few ideas, but would like to see some actual examples (ideally, safe and tried).

我的想法:

  • C 中的伪模板,其中模板参数被预处理器定义替换.它可以不包含在内,但函数可能太大或太多,因此制作一个单独的文件是有意义的.
  • 逐块结构/类构造(片段连接).它可能有助于在 C 中模拟继承,并在定义具有公共成员的结构时防止代码重复.
  • 查找表和其他编译时数据结构(同样,借助预处理器定义).

推荐答案

#include "file" 意思是把头文件的内容全部放上,而不是#include行.

#include "file" means take the header file and put all of its content instead of the #include line.

我们通常使用头文件进行类型定义和向源文件添加前向声明.在一个文件中定义相同类型两次(循环包含总是会导致它)会产生编译错误,因此我们使用 #ifndef#pragma once.(或两者兼有)

We usually used headers for type definitions and for adding a forward declarations to a source files. defining same type twice in a file (a circular include will always cause it) gives compilation error, therefore we use #ifndef or #pragma once. (or both)

但我们也可以放置重复的代码和宏并多次包含它,甚至在同一个文件中.在这种情况下,我们不会使用 #ifndef#pragma once.如果这样做,您必须格外小心,并且只有在您知道自己在做什么的情况下才这样做.

But we also can to put a repeating code and macros and include it several times, even in the same file. in such as case, we won't use #ifndef nor #pragma once. If you do so you must be extra careful, and do it only if you know what you are doing.

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

For example: If in some OS calling a specific system function (or even a c macro like: offsetof) cause a bunch of warnings, and it is bothering you, and you sure your code is good, but you don't want to disable all the warnings you've got on all the project or the file, you just want to disable it when you call the specific 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__

这会让你的代码看起来很脏,特别是如果你多次调用这个函数.

This will make your code to look very dirty, especially if you call the function several times.

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

One possible solution, (I'm not suggesting it is the best one...) is to make 2 headers, in one to suppress the warnings and in the other to cancel the suppression.

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

In that case your code may look like this:

#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"

相关文章