码迷,mamicode.com
首页 > 其他好文 > 详细

两种解决头文件被重复包含方法的联系与区别

时间:2016-05-12 19:06:18      阅读:285      评论:0      收藏:0      [点我收藏+]

标签:

       在制作C/C++项目的过程中,应该会遇到关于头文件被重复包含的问题,几乎每一个C/C++程序员都应该知道如何来解决这一问题。通常来说,我们通常可以用两种方式来解决这一问题。

第一种 ---- 利用以下形式:

#ifndef  __XX_H__                                                                              #ifndef   XX_H

#define __XX_H__                        写成这样也可以-->                        #define  XX_H 

<头文件定义正文>                                                                              <头文件定义正文>

#endif                                                                                                                                                                #endif

__XX_H__  其实就是一个标志,(这个标志本来可以随便自己定义,但是为了防止混乱,所以一般都会采用自己的文件名字:__XX_H__),而且 ifndef 也可以写成 if !defined 效果是一样的。(注:ifndef  不要错写成  ifdef)

当然还有第二种 ---- 在windows平台下,有一个很方便的宏: #pragma once

这个宏我们用MSDN打开查看一下可以得到以下解释内容:

"Specifies that the file will be included (opened) only once by thecompiler when compiling a source code file."
从字面上看这句英文的主要意思就是防止头文件被重复包含。于是我们就想,既然这两种方法都可以起到防止头文件被多次包含的作用,那么这两种方式有什么不同呢,或者说有什么相同之处呢?


首先我们来说一说重复包含的影响:

C/C++在预处理的时候,include相同的文件,预处理器会检查XXX是否有定义再决定要不要复制内容,重复包含会是编译器多检查几次而已。另外在使用增量编译的时候,这个文件变化,所有 include 这个文件的文件都需要重新编译,即使没有去使用里面的任何内容,所以重复包含最经常带来的错误就是重定义。


在用VC6.0向导生成的头文件中,经常可以看见如下的代码段:

  #if !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_)
  #define AFX_RESIZABLELAYOUT_H__INCLUDED_

  #if _MSC_VER > 1000
  #pragma once
  #endif // _MSC_VER > 1000

  ...

  #endif // !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_)

  对于宏有基本了解的朋友应该都知道,头文件中如下的宏定义,是为了避免同样的头文件在同一个.C文件或者.CPP文件多次包含。

  #if !defined(XXX)
  #define XXX
  #endif

由此可知这两种方式都可以很好的起到避免重复包含的作用,但是这两种有什么区别呢?

       疑惑就此产生了,既然宏"#if !defined"已经有这个作用了,为何还要一个"#pragma once"呢?

       其实虽然"#ifndef"和"#pragma once"都有避免重复包含的功能,但是在实现上还是有区别的。举一例如下:


  // Test1.h
  #ifndef  __COMMENT_CONVERT_H__
  #define __COMMENT_CONVERT_H__
  ...
  #endif

  // Test2.h
  #pragma once
  ...

  // Test.cpp
  #include "Test1.h" //
  #include "Test1.h" //
  #include "Test2.h" //
  #include "Test2.h" //

  ...

  头文件Test1.h中用宏来避免重复,头文件Test2.h中用#pragma once来避免重复。编译Test.cpp,将需要打开Test1.h两次,第一次发现宏__COMMENT_CONVERT_H__没有定义,接着就处理宏定义;第二次打 开Test1.h时,发现宏__COMMENT_CONVERT_H__已经定义过了,编译器就会略过宏定义部分,直到处理完Test1.h末的#endif。

  而由于头文件Test2.h使用#pragma once来避免重复定义的,在编译Test.cpp的过程中,Test2.h只会被打开一次,也就是处理到第3行的时候。因为Test2.h用的 是#pragma once,所以在处理完第3行后,编译器已经知道包含了一次Test2.h,在它(编译器)处理第4行代码时,发现Test2.h已经包含过了,忽略掉第 4行代码,也就不需要再次打开Test2.h进行判断了。

  总结一下,除了#pragma once是微软编译器所特有的之外,用宏和#pragma once的办法来避免重复包含头文件,主要区别在于宏处理的方法会多次打开同一头文件,而#pragma once则不会重复打开,从而#pragma once能够更快速。

用更确切的语言总结一下就是:#pragma once指定当前文件在构建时只被包含(或打开)一次,这样就可以减少构建的时间,因为加入#pragma once后,编译器在打开或读取第一个#include 模块后,就不会再打开或读取随后出现的同#include 模块。

两种解决头文件被重复包含方法的联系与区别

标签:

原文地址:http://blog.csdn.net/loving_forever_/article/details/51352407

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!