首先,在现代的C++编译器中,您可以使用
#pragma once
代替include guards。
然后,您的示例有点混乱,因为您在头文件中定义了一个
extern
函数。通常,
include
文件用于定义函数的声明,而不是函数的定义。
如果您在头文件中定义函数,并且该头文件被多个CPP源文件使用,则此函数将被多次定义为相同的名称,并且在链接程序时会出现错误!
更好的包含方式是:
#ifndef HEADER_FILE
#define HEADER_FILE
int two(void);
#endif
或者
#ifndef HEADER_FILE
#define HEADER_FILE
static int two(void) { return 2; }
#endif
或者
#pragma once
static int two(void) { return 2; }
在最后一个情况下,如果包含此头文件的每个CPP源文件中都定义了函数
two()
,但是此函数是静态的,因此CPP源文件正确编译,CPP程序也能够正常链接。
在您的问题中,您问道
在哪种情况下我们可以忘记添加#define HEADER_FILE?
个人而言,在非常特殊的棘手情况下,我会使用相同的头文件。
以下两个包含是一个“好”的例子:
#pragma once
#define MODULEx(n) extern StructDefineMODULE MODULE_##n;
#include "XTrace.Modules.h"
#undef MODULEx
#define MODULEx(n) { #n, &MODULE_##n } ,
static struct ModuleTRACE tModuleTrace[]
= {
#include "XTrace.Modules.h"
{ 0, 0 }
};
其中XTrace.Modules.h
的包含如下:
MODULEx( BBDIXFILE )
MODULEx( CECHO )
MODULEx( INITDBFIELD )
MODULEx( IVIRLUX )
最初的回答:
第一个包含文件中包含了
#pragma once
,并且两次调用相同的内部包含文件。
第一次调用是为了定义StructDefineMODULE结构的外部声明。
第二次调用是为了初始化ModuleTRACE结构数组。
由于这个包含文件被调用了两次,所以必须避免使用
#pragma once
或
#ifndef
。
在使用内部包含文件时,我可以百分之百确定用于定义StructDefineModule的所有元素也用于初始化tModuleTrace[]数组。
内部包含文件的结果如下:
/*******************************************************************
* XTrace.Configuration.h
********************************************************************
*/
#pragma once
extern StructDefineMODULE MODULE_BBDIXFILE;
extern StructDefineMODULE MODULE_CECHO;
extern StructDefineMODULE MODULE_INITDBFIELD;
extern StructDefineMODULE MODULE_IVIRLUX;
static struct ModuleTRACE tModuleTrace[]
= { { "BBDIXFILE" , &MODULE_BBDIXFILE }
, { "CECHO" , &MODULE_CECHO }
, { "INITDBFIELD" , &MODULE_INITDBFIELD }
, { "IVIRLUX" , &MODULE_IVIRLUX }
, { 0, 0 }
};
我希望这可以帮助您理解为什么在某些情况下可以避免使用include guards!"最初的回答"。请看以下内容:
我希望这可以帮助您理解为什么在某些情况下可以避免使用include guards!