870920 Menu

SwingCoder之C++备忘录·8

预处理

所有预处理指令并非C++运行时所执行的语句,而是编译前先行展开的文本内容或编译指令。预处理指令均以“#”开头(using指令除外),一条一行,不以分号结尾。代码编译前的预处理主要包括:

 将其他文件包含到当前文件中(#include),即:文件展开。
 替换宏定义(将代码中由#define所定义的符号常量替换为原始语句)。比如预定义了:#define PI 3.14159,则代码中的PI全部替换为3.14159。通常在头文件中进行#define预定义(取消宏定义的语法为:#undef 宏定义名称)。
 执行条件编译(#if、#else、#elif、#ifndef、#ifdef,以上每个#if均由#endif结尾)。#if 0和#endif所包裹的代码不参与编译
 执行预处理指令(#error、#pragma、using指令和using声明等)

关于#include头文件:
 使用C++标准库或IDE中PATH所设置的头文件:#include <vector>
 使用自定义的类或第三方类:#include “C.h” // 先搜索当前目录,而后搜索PATH和库目录。
 A类继承自B类,A类的h头文件中必须 #include “B.h”
 A类h头文件中使用了C类的对象(非指针和引用,包括数据成员、函数参数和函数返回值),必须 #include “C.h”
 A类h头文件中使用了D类的指针或引用(未使用其栈对象),无需#include “D.h”,前置声明即可:class D;
 永远不要在两个h头文件中进行双向include(循环依赖),其中之一应使用前置声明。
 通常,某个类的cpp源文件不仅需要#include本类的头文件,还需要#include头文件中前置声明的其他类的h文件。
 cpp源文件中永远不要include另一个cpp源文件(除非该cpp文件不参与编译,或有其它玄机)。
 h头文件中应尽可能的不include其他类的h头文件,以减少编译时的依赖性。
 h头文件应始终使用#ifndef、#define…#endif“头文件卫士”进行包裹。
 除了整个头文件所用的“头文件卫士”之外,本文件中所包含的具体头文件,或者源代码,也可使用条件编译。满足一定条件时,包含该头文件或执行该代码,不满足时则编译时不予包含或不予执行。所满足的条件通常采用开关式宏定义,比如:
// 提前定义条件编译宏,若要执行WIN_32条件编译中的语句,定义为1,否则定义为0
DEFINE WIN_32 1
// 某个类的头文件中
#ifdef WIN_32
#include <windows.h>
#endif
void sayHello()
{
#ifdef WIN_32 // 源代码中的条件编译
cout << “Hello Windows.”;
#else
cout << “Hello non Windows.”;
#endif
}