条件编译用于文件包含保护

1.条件编译(Conditional Compilation)命令常用的形式:

  • 当所指定的标识符已经被#define命令定义过,则只编译程序段1,否则编译程序段2,#ifndef则相反, #endif用来限定#ifdef命令的范围。其中#else部分可以省略。
#ifdef 标识符
 程序段1
#else
 程序段2
#endif
  • 类似地,如下形式中,根据指定的表达式值来选择所编译的程序段。
#if 表达式
 程序段1
#else
 程序段2
#endif

2.头文件包含保护(Include guard

header files are #included and not compiled, whereas source files are compiled and not #included.

如果在源文件中重复#include同一个头文件,很可能会出现编译错误,一个简单的例子:

// myclass.h

class MyClass
{
  void DoSomething() { }
};
// main.cpp
#include "myclass.h"   // define MyClass
#include "myclass.h"   // Compiler error - MyClass already defined

这种情况很常见,只不过不像上面那么明显,更一般的情况是,#inlclude多个包含了同样头文件的头文件:

// x.h
class X { };
// a.h
#include "x.h"

class A { X x; };
// b.h
#include "x.h"

class B { X x; };
// main.cpp

#include "a.h"  // also includes "x.h"
#include "b.h"  // includes x.h again!  ERROR

鉴于此,可能得到建议:not to put #include in header files。然而,这不是一个好的建议。事实上,头文件中使用#inlude命令并没有什么问题,并且通常是很常用的。两点需要注意:

  • Only #include things you need to include.
  • Guard against incidental multiple includes with include guards.

Include Guard技术可以解决上面的问题,例子:

//x.h

#ifndef X_H   // if x.h hasn't been included yet...
#define X_H   // #define this so the compiler knows it has been included

class X { };

#endif 

根据条件编译很容易理解,x.h在第一次被included的时候,将定义标识符 _X_H_INCLUDED,这样的话,如果x.h再次被included,编译器则会跳过整个头文件(#ifndef和#endif之间的程序段),不编译这部分内容。这样就解决了上述重复包含带来的重定义问题。

一个重要的C++软件工程概念,又称“预处理器封套”,在头文件中使用预处理器封套,从而避免头文件中的代码被多次包含到同一个源文件中的情况。由于一个类只能被定义一次,因此使用这样的预处理器指令阻止了重复定义的错误。
预处理指令中符号常量命名的通常约定是将头文件名大写,其中的dot用下划线代替。

重要参考:Headers and Includes: Why and How

posted on 2015-09-22 13:15  conard  阅读(260)  评论(0编辑  收藏  举报