C++中避免头文件冲突之#ifndef篇

在头文件中使用#ifdef和#ifndef是非常重要的,可以防止双重定义的错误。

如你在头文件aaa.h中定义了一个类aaa如下:   
class   aaa   
{   
};   
如果两次#include   "aaa.h"(不见得是直接,也有可能两个不同的头文件中都包含了这个头文件)就会出错,因为相同的类不能定义两次。把aaa.h稍做修改:   
#ifndef   _aaa_   
#define   _aaa_   
class   aaa   
{   
};   
#endif   
就可以避免这样的问题。因为当你已经包含过这个文件,_aaa_就会有了定义,那么#ifndef的条件为假,就不会再执行后面的类定义了。

 

#ifdef和#endif必须成对使用。   
从理论上讲可以出现在任何地方(头文件和实现文件中)   
通常为了防止头文件被多次包含,在头文件中使用是必须的:   
如:#ifndef   MY_HEAD_H   //头文件开头,名字是任意的,注意不要和其它头文件冲突  

(一)头文件声明   
      #ifndef

      #define
      #endif     //头文件结尾

有时候,在b.h中会include   "a.h"   
在"c.h"中会include   "b.h"及include"a.h",   
这时,如果不用ifndef/endif,就会包含两次a.h,产生错误。此时正确的做法就是:

"a.h"

---------------------------------------------------------------------------------------------------------------

#ifndef _A_H_

#define _A_H_

.....//content of the head file

#endif

"b.h"

----------------------------------------------------------------------------------------------------------------

#include "a.h"

........//content of "b.h"

"c.h"

----------------------------------------------------------------------------------------------------------------

#include "a.h"

........//content of "c.h"

这样做应该就能解决问题了,但是,我不建议这么做,因为就算这样条件预编译了,整个图文集内容会被忽略,但预处理器还是会把整个文件读入的。由于这种预处理将托慢编译速度,所以如果可能,应该避免出现多重包含(也就是在<#pragma once与 #ifndef的区别>这篇博文里写的[1])。另外一种方法就是[1]里的#pragma once

条件编译,满足条件就编译,否则就不编译,如果有一段代码有时候你想要,有时候又不想编译(比如为了调试),可以这样写:   
#if   1(0)   
          xxxxxx   
          xxxxxx   
#endif   
需要的时候写1,不要的时候改为0就可以了

文件中的#ifndef 
头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。


还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的:

#ifndef <标识> 
#define <标识>

...... 
......

#endif

<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h

#ifndef _STDIO_H_ 
#define _STDIO_H_

......

#endif

2.在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。

#ifndef AAA
#define AAA
...
   int i;
   ...
#endif
里面有一个变量定义
在vc中链接时就出现了i重复定义的错误,而在c中成功编译。

结论:

(1).当你第一个使用这个头的.cpp文件生成.obj的时候,int i 在里面定义了当另外一个使用这个的.cpp再次[单独]生成.obj的时候,int i 又被定义然后两个obj被另外一个.cpp也include 这个头的,连接在一起,就会出现重复定义.

(2).把源程序文件扩展名改成.c后,VC按照C语言的语法对源程序进行编译,而不是C++。在C语言中,若是遇到多个int i,则自动认为其中一个是定义,其他的是声明。

(3).C语言和C++语言连接结果不同,可能(猜测)时在进行编译的时候,C++语言将全局
变量默认为强符号,所以连接出错。C语言则依照是否初始化进行强弱的判断的。(参考)

解决方法:

(1).把源程序文件扩展名改成.c。

(2).推荐解决方案:
.h中只声明 extern int i;在.cpp中定义

<x.h>
#ifndef __X_H__
#define __X_H__
extern int i;
#endif //__X_H__
<x.c>
int i;

[1].<#pragma once与 #ifndef的区别>: http://hi.baidu.com/christole/blog/item/78ff759558c33c05d21b70bb.html
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: #ifndef/define是C/C++的预处理指令,用于防止头文件被重复包含。当头文件被多次包含时,ifndef/define会防止其的声明和定义被重复编译,从而避免编译错误和重复定义的问题。在头文件使用#ifndef/define的常见格式为: #ifndef HEADER_FILE_NAME_H #define HEADER_FILE_NAME_H // 头文件内容 #endif 其,HEADER_FILE_NAME_H是头文件的名称,可以是任意字符串,但通常使用头文件的文件名加上_H后缀。当头文件被第一次包含时,ifndef/define会定义一个名为HEADER_FILE_NAME_H的宏,然后执行头文件的内容。当头文件被再次包含时,由于HEADER_FILE_NAME_H已经被定义,ifndef/define会跳过头文件的内容,从而避免重复编译。 ### 回答2: 在头文件使用#ifndef/define指令是为了防止头文件被重复包含。头文件的主要作用是包含函数和数据的声明,用于在多个源文件共享代码。如果不使用ifndef/define指令,当多个源文件引用同一个头文件时,编译器会将头文件的内容重复包含多次,这会导致重复定义的错误。 #ifndef是预处理指令,意为“如果未定义”。当#ifndef指令后面紧跟的宏标识符未被定义时,即判断为真,则编译器会执行#ifdef和#ifndef之间的代码;否则,即判断为假,则会跳到endif指令后的代码继续执行。 #define是定义宏的指令,用于给宏标识符赋值。当头文件第一次被包含时,ifndef指令判断为真,编译器会执行相应的代码,并在代码执行完后定义该宏标识符;当头文件被多次包含时,由于该宏标识符已被定义,ifndef指令判断为假,编译器会跳过该指令后的代码,避免重复定义的错误。 通过使用#ifndef/define指令,可以保证头文件只被包含一次。这对于编译大型项目时非常重要,可以提高编译效率、避免冲突和错误。此外,还可以减少代码冗余,使代码更加清晰和易于维护。 总之,ifndef/define指令在头文件的作用是防止头文件被重复包含,确保头文件只被编译一次,避免重复定义和冲突的问题。 ### 回答3: 头文件ifndef/define是一种条件编译指令,用于防止头文件的重复包含。 头文件的作用是用来声明函数、结构体、宏等内容,供其他源文件使用。由于头文件可能被多个源文件包含,而多次包含同一个头文件会导致重复定义的问题,因此需要使用ifndef/define指令来解决这个问题。 首先,在头文件的开头使用ifndef指令,判断一个特定的标识符是否已经被定义。如果这个标识符已经被定义,说明这个头文件已经被包含过,就直接跳过该头文件的内容。如果这个标识符没有被定义,说明这个头文件还没有被包含过,就执行接下来的代码。 接着,在ifndef指令的下一行使用define指令,定义这个标识符。这个定义只是一个占位符,没有实际的值。目的是为了防止以后再次包含这个头文件时,ifndef指令的条件不再成立,从而执行接下来的代码。 通过使用ifndef/define指令,可以有效地防止头文件的重复包含问题,确保头文件的内容只被编译器处理一次。这样在多个源文件包含同一个头文件时,不会发生重复定义错误,保证了代码的正确性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值