本学习笔记来源于免费教程 Learn C++
2.10 预处理器简介
2.10.1宏定义
基本语法:
#define identifier substitution_text
当预处理器遇到此指令时,标识符的任何进一步出现都将替换为substitution_text。标识符传统上以全部大写字母键入,使用下划线表示空格。如果substitution_text为空,则标识符被替换为空格。
例子:
#include <iostream>
#define MY_NAME "Alex"
int main()
{
std::cout << "My name is: " << MY_NAME;
return 0;
}
但教程并不推荐使用该语法
2.10.2 条件编译
条件编译预处理指令允许你在给定条件下的代码会不会被编译,功能类似if 判断条件:注释 or 执行
。有很多不同的条件编译指令,但我们只会覆盖最常用的三个:#ifdef,#ifnf 和 #endif
。
如果被定义到函数内,则类似于局部变量,作用范围只限于函数。
#include <iostream>
#define PRINT_JOE
int main()
{
#ifdef PRINT_JOE // if PRINT_JOE is defined
std::cout << "Joe\n"; // execute this code
#endif
return 0;
}
与#ifndef
是相反的#ifdef
,因为它可以让你检查的标识符是不是没有被定义。
还有 #if 0
和#endif
搭配使用
#if 0 // Don't compile anything starting here
std::cout << "Bob\n";
std::cout << "Steve\n";
#endif // until this point
2.11 头文件
当声明越来越多时,就很不方便,可以把这些声明都放到一个文件,称为头文件,这样以后只需要include头文件就行了。
使用有角度的括号来告诉预处理器我们包含了编译器附带的头文件,因此它应该在系统目录中查找该头文件,如:#include <iostream>
。双引号告诉预处理器这是我们提供的用户定义的头文件,因此它应首先在当前目录中查找包含源代码的头文件。如果它没有找到头文件,它将检查您在编译器IDE设置中指定的任何其他包含路径。失败了,它将回退到检查系统目录。如:#include "your_header_files.h"
当包含标准库中的头文件时,如果存在,则使用无扩展版本(不带.h)。用户定义的标头仍应使用.h扩展名。
如何包含其他目录的头文件
方法①:包含相对路径
但是如果变更目录,该方法会需要改动比较麻烦
#include "headers/myHeader.h"
#include "../moreHeaders/myOtherHeader.h"
方法②:编译器里面设置头文件目录
这样当它在当前目录中找不到它们时会看到它们。这通常可以通过在IDE项目设置中设置包含路径或搜索目录来完成。
VS里面:选中项目,右键—属性—VC++目录—包含目录
这种方法是全局影响,对以后所有的项目都有用
如果只是想对当前项目添加头文件:
VS里面:选中项目,右键—属性—C/C++—常规—附加包含目录
2.12 标头保护(header guards)
假如头文件里面有重复的声明,这样主程序导入之后,就会报重复定义的错误。所以可以通过标头保护避免问题,思路就是加上条件编译指令,如下:
#ifndef SOME_UNIQUE_NAME_HERE
#define SOME_UNIQUE_NAME_HERE
// your declarations (and certain types of definitions) here
#endif
其中 SOME_UNIQUE_NAME_HERE 按照约定是头文件的全部名字,并且全部大写,比如,luck.h,写成LUCK_H。
为了避免重复,推荐 一些好的建议是<PROJECT> _ <PATH> _ <FILE> _H,<FILE> _ <大随机数> _H 或 <文件> _ <创建日期> _H的命名约定
例子如下:
square.h
#ifndef SQUARE_H
#define SQUARE_H
int getSquareSides()
{
return 4;
}
#endif
geometry.h:
#ifndef GEOMETRY_H
#define GEOMETRY_H
#include "square.h"
#endif
main.cpp中:
#include "square.h"
#include "geometry.h"
int main()
{
return 0;
}
在预处理器解析所有包含之后,此main()程序如下所示:
#ifndef SQUARE_H // square.h included from main.cpp,
#define SQUARE_H // SQUARE_H gets defined here
// and all this content gets included
int getSquareSides()
{
return 4;
}
#endif // SQUARE_H
#ifndef GEOMETRY_H // geometry.h included from main.cpp
#define GEOMETRY_H
#ifndef SQUARE_H // square.h included from geometry.h, SQUARE_H is already defined from above
#define SQUARE_H // so none of this content gets included
int getSquareSides()
{
return 4;
}
#endif // SQUARE_H
#endif // GEOMETRY_H
int main()
{
return 0;
}
头文件里面最好不要有定义,因为如果头文件被main()文件和其他的cpp文件包含,那么在main()里面,标头保护不会识别出其他文件里面已经被定义过了,这样就会出现重复定义。所以头文件里面只放声明,不要放定义。
还有一种头部保护的写法。但这不是标准c++的语言,可能有的不支持。
#pragma once
#pragma once
// your code here