C++头文件

阅读说明:前面有些名词不懂没关系,后面都会解释

头文件

有两种文件拓展名.h 和.hpp(将.cpp的实现代码混入.h中变成.hpp文件—一般用于类模板)

头文件布局

  1. 预处理块 (带#的)
    • 防卫式声明
    • 预处理指令
  2. 前置声明
  3. 类声明
  4. 函数声明

示例

头文件的处理

先大致解释一下编译器和预编译器的作用

编译器

将程序员写的代码转换为机器可读的二进制指令

预编译器

处理#开头的指令,进行文本替换(在指令处展开被包含的文件)。可以放在程序中的任何位置。

头文件本身不直接参与编译,头文件先被预编译器处理,再由编译器间接编译

处理预编译指令,处理规则如下

  • 将所有的"#define"删除,并且展开所有的宏定义
  • 处理所有的条件预编译指令,比如"#if"、“#ifdef”、“endif”
  • 处理"#include"预编译指令,将被包含的文件直接插入到预编译指令的位置。
  • 删除所有的注释
  • 添加行号和文件标识,以便于编译时产生调试用的行号及编译错误警告行号。
  • 保留所有的#pragma,因为编译器要使用他们,预编译器无法处理

这里参考文章

预处理指令(预编译指令)

预处理指令结构

是以#开头的代码行,#后是指令关键字

预处理主要功能

  • 1. 宏定义 #define 语法

    #define  标识符   值
    //     (👆大写)(👆可以是一个常量表达式或字符串常量,或带参数--带参数的宏类函数调用)
    
  • 2. 条件编译: 根据表达式的值某个特定的宏是否被定义来确定哪些代码被编译,而哪些是不被编译的

    • #if和#endif终止:根据表达式的值确定编译条件
    • #ifdef和#ifndef终止:根据某个特定的宏是否被定义确定编译条件
    • #else:用于某个#if/#ifdef指令之后,当前面的#if指令的条件不为真时,就编译#else后面的代码
    • #elif:综合了#else和#if指令的作用(类else if())
  • 3. 文件包含 #include

    • 预编译器要想处理头文件必须要能找到这个头文件,根据其查找方式分为两种使用头文件的方式

       #include <code.h>  
       //一般用于包含系统文件
       //在系统头文件所在的路径下(系统目录,也叫头文件的标准目录)开始找
       #include "code.h"  
       //一般用于包含项目文件
       //以源文件所在位置(当前目录,也叫项目目录)开始查找,如果找不到再去系统目录找
      

      当在这些路径中找不到include的头文件时就会抛出错误“fatal error: ***.h: No such file or directory”

防卫式声明

作用

如果这个头文件没有被定义,那就定义它,如果已经定义过了,那就忽略。

防止由于同一个头文件被包含多次,而导致了重复定义(Redefinition)。

两种
  1. 宏定义(header guard,亦称include guard或macro guard)
#ifndef _FILENAME_
#define _FILENAME_
//...
#endif

//#ifndef 依赖于宏定义名,当宏已经定义时,#endif之前的代码就会被忽略,但是这里需要注意宏命名重名的问题;
  1. 编译器指令 #pragma once
两种方式的比较
  • #pragma once相比 宏定义 具有两个优点:

    ① 更快。编译器不会第二次读取标记#pragma once的文件,但却会读若干遍使用header guard 的文件(寻找#endif);

    ② 更简单。不再需要为每个文件的header guard取名,避免宏名重名引发的"找不到声明"问题。

  • 缺点则是:

    #pragma once只能保证物理上的同一个文件不会被编译多次,但是当两个不同的文件内容相同时,pragma不能保证它们不被重复包含(不过这种重复包含很容易被发现并修正)。而且这是微软提供的编译器命令,当代码需要跨平台时,需要使用宏定义方式

这里参考文章

部分预处理指令

在这里插入图片描述

前置声明

作用

是变量/常量、类、函数、模板的纯粹声明

注意事项

  • 类的成员函数无法单独做前置声明
  • 只能定义指向前置声明的类的指针或引用

什么时候该用前置声明,什么时候该用#include?

  • 尽量避免前置声明那些定义在其它项目中的实体,优先使用#include。
  • 对于函数,应总是使用#include。
  • 类模板应该优先使用#include。

常用系统头文件

#include<iostream> //I/O流(cin>>,cout<<...)
#include<algorithm>//常用算法
#inclde<cmath>//数学函数(如max(),min(),abs()...),继承自C语言的math.h
#include<string>//字符串
#include<cstdio>//C语言
//数据结构类:
#include<queue>//普通队列
#include<deque>//双向队列
#include<stack>//栈
#include<list>//列表
#include<vector>//动态数组
#include<map>//图
#include<set>//集合

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值