20.2.4 #ifdef、#ifndef与重复包含
ifdef、#ifndef用来测试某个宏是否被定义,“#ifdef”相当于“#if defined()”,“#ifndef”相当于“#if!defined()”,经常用于避免头文件的重复引用。
头文件重复引用往往是由于包含嵌套造成的,例如某个cpp文件中包含如下头文件。
#include<A.h> #include<B.h>而A.h中包含了B.h,如下所示。 #include<B.h>
这意味该cpp文件对应的编译单元中,头文件B.h被引用了两次,这就是重复包含。
重复包含带来的问题便是重复定义,前面讲过对普通变量和普通函数来说,定义只能有一次,而声明可以有多次,如果定义多次,编译器就会报错。头文件中往往定义了大量的宏,根据编译器规则,宏可以重复定义,前提是这些定义必须是相同的,因此,如果头文件只是提供接口作用,不对变量进行定义,不包含函数的具体实现,重复包含似乎不会引发什么问题。但是在编写头文件时,很多程序员并不遵守这些规则,有的干脆把全局变量定义在头文件中,所以防止重复包含十分重要。
在头文件编写时使用如下格式可有效防止本编译单元内的头文件重复包含。
//文件名:headfile.h #ifndef_HEADFILE_200802241900 #define_HEADFILE_200802241900 ……//原来headfile.h中的内容 #endif
上述代码中“HEADFILE200802241900”仅是示例,可根据不同的头文件自由设置,只要保证在本编译单元中唯一即可,推荐写法是“两个下划线+头文件名+日期时间”。这样,当在组成某个单元的cpp文件和h文件中第1次“#include<headfile.h>”时,由于宏“HEADFILE200802241900”尚未定义,满足“#ifndefHEADFILE200802241900”这个判断,故执行“#defineHEADFILE200802241900”,并将原来headfile.h头文件中的内容插入到包含处,如果出现了对headfile.h的重复引用,在本编译单元内第二次“#include<headfile.h>”时,判断条件“#ifndef_HEADFILE_200802241900”不再满足,所以不会将原来headfile.h中的内容插入到包含处,会直接跳到#endif很好地防止了头文件被重复引用。
注意
与条件编译不同的是,#ifdef和#ifndef既可作用于对象宏,又可作用于函数宏。