五、C++中的头文件 Header Files

2023-05-16

头文件 Header Files传统上用于声明某些函数类型,以便可以用于整个程序中。

例如:在一个文件1中创建函数,然后想在另一个文件2中使用,尝试编译此文件2时,C++不会直到这个文件1的存在,所以需要一个共同的地方来存放声明(并不是定义,因为函数的定义只可以有一次),声明中没有实际的函数定义,没有函数主体,

假定有个函数Log,作用时打印输出,接收一个const char "message",然后cout该信息

//Math.cpp
#include <iostream>

void Log(const char* message)
{
	std::cout << message << std::endl;
}

int main()
{
	std::cout << "Hello World!" << std::endl;
	std::cin.get();
}

//新建Log.cpp
void InitLog()
{
	Log("Initialized Log");
//此处Log会报错,这个Log函数并不存在于该文件,该文件不知道Log函数的存在

}

//为了没有error,修改Math.cpp
#include <iostream>

void Log(const char* message)
{
	std::cout << message << std::endl;
}

int main()
{
	Log("Hello World!");//编译不报错
	std::cin.get();
}

//但是Log.cpp仍然报错,Log仍然不存在
//Log.cpp需要什么才会没有错误?告诉Log.cpp文件,Log函数存在,只是定义于别的地方
//使用函数声明!!!
//修改Log.cpp
//直接复制粘贴Log函数的函数签名到Log.cpp文件,尾部用分号结束,例:Log.cpp
void Log(const char* message);//仅仅是函数的声明,无函数主体
void InitLog()
{
	Log("Initialized Log");//编译不再报错
}

如果另外创建了别的文件需要使用Log函数:

将Log函数的声明void Log到处复制粘贴?可以但不必要,Header File可以解决该问题。

头文件一般被include到.cpp文件中,将头文件的内容复制粘贴进.cpp文件中,通过#include 预处理语句来实现,#include有从文件复制粘贴到其他文件的能力

创建头文件Log.h

系统自动插入了#pragma once

头文件Log.h中写入函数声明,此时任何想要使用Log函数的地方只需要经过include就可以使用

//Log.h
#pragma once

void Log(const char* message);
void InitLog();

//Log.cpp
#include <iostream> //include后,error消失
#include "Log.h"

void InitLog()
{
	Log("Initialized Log");
}

void Log(const char* message)
{
	std::cout << message << std::endl;
}

//Main.cpp
#include <iostream>
#include "Log.h"


int main()
{
	InitLog();
	Log("Hello World!");
	std::cin.get();
}

header file中系统自动插入的#pragma once:属于预处理指令,意思是:该文件只include一次

pragma once被称为header guard(头文件保护符),防止把单个头文件多次include到一个单一翻译单元(一个.cpp文件)里,但是不会防止把头文件include到程序的各处。

把单个头文件多次include到一个单一翻译单元(一个.cpp文件)里会得到一个重复的错误。

创建struct示意:

//Log.h
//#pragma once 被注释掉

void Log(const char* message);
void InitLog();

struct Player {};

//Log.cpp文件中,头文件include两次,此时编译会得到'player' struct typr redefinition
#include <iostream> 
#include "Log.h"
#include "Log.h"
void InitLog()
{
	Log("Initialized Log");
}

void Log(const char* message)
{
	std::cout << message << std::endl;
}

程序编写时会include多个头文件,防止声明重复

例,新建Common.h

//Commom.h
#pragma once
# include "Log.h"

//Log.h
//#pragma once

void Log(const char* message);
void InitLog();

struct Player {};

//Log.cpp
#include <iostream> 
#include "Log.h"
#include "Common.h"
void InitLog()
{
	Log("Initialized Log");
}

void Log(const char* message)
{
	std::cout << message << std::endl;
}


依然会报错重定义

 原因:将Log include了两次(Log.cpp+Common.h)

将Log.h文件中的#pragma once解除注释

成功编译(解除注释后,察觉到Log.h已被include,不会在二次include)

添加头文件保护符的另外一种方式:(传统方式添加头文件保护符#ifndef)

        #ifndef

Log.h

#ifndef _LOG_H
#define _LOG_H

void Log(const char* message);
void InitLog();

struct Player {};
#endif

#ifndef _LOG_H 首先检查_LOG_H这个符号是否存在,如果没有定义,它将把以下代码include到编译里;如果已经被定义了,那么这些都不会被include,会全部被禁用。通过了第一个条件检查后会定义Log.h。下次运行这段代码时,它是已经被定义的状态,所以不会再重复

将文件内容复制到Log.cpp中,注释掉两个原本的.h文件,首次粘贴一切正常,第二次内容变灰,因为Log.h已经被定义了

多数编辑器都支持#pragma once

头文件保护符一起,include语句间会有差异,""或<>

<>是让编译器在所有include路径里搜索文件

""用于include文件存在于该文件的相对位置

例如:有Log.h文件存在于Log.cpp文件的上一级目录,此时可以使用../来返回,返回相对本文件的上一级目录。#include "../Log.h"

对于<>来说,只是说存在于所有include目录的某一个里

其实,""也可以用于编译器include目录的位置

<>只用于编译器的include路径,""用于所有

iostream没有文件扩展名,是个没有扩展名的文件。为了区分C标准库与C++标准库,C标准库的头文件一般都有.h扩展名,而C++没有

10

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

五、C++中的头文件 Header Files 的相关文章

  • C++ 头文件的解析器可以使用标准 Linux 工具提取函数吗?

    有这样的事吗 我需要从头文件中提取 C 函数及其使用的所有参数 如果我能使用标准的 Linux 程序就好了 您可以使用 Understanding 4 C 这是一个前端工具 可以浏览源代码并为源代码生成指标 它还具有强大的API 允许您编写
  • pimpl 使模板编码不那么混乱

    我正在尝试创建一个更清晰的头文件 以供头类的参考 文档使用 同时仍然认识到模板的便利性 所以我有一个快速的 h hpp 文件 mempool h namespace internal template
  • 设置日期标头以降低 SpamAssassin 分数

    我使用了测试服务 verifier port25 com 来检查从我的 PHP 脚本发送电子邮件时发生的情况 由于某种原因 即使启用了 SPF 和 DKIM 它们最终还是出现在我的 GMail 垃圾邮件文件夹中 事实证明 SpamAssas
  • 在 Objective-C 中包含头文件的成本

    这似乎是一个非常愚蠢的问题 但是包含的成本是多少 实际上 调用 import Objective C 中的头文件 我厌倦了在不同位置不断包含相同的标头 所以我决定简单地创建一个GlobalReferences h包含几个常用引用标头的文件
  • 显示名称而不是电子邮件的电子邮件标题的格式是什么?

    我正在尝试创建一个 php 脚本 该脚本将使用 mySQL 数据库为我处理邮件列表 并且我已经准备好了大部分内容 不幸的是 我似乎无法让标题正常工作 而且我不确定问题是什么 headers From email protected cdn
  • 操作 TCP 标头中 ISN 编号的最有效方法 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我目前正在尝试编写一个程序 该程序将
  • 如何使用 jquery mobile 和 data-position="fixed" 来“修复”页眉页脚位置

    我正在使用 jquery mobile 对于页眉 页脚 我使用 data position fixed 但是 当我们滚动页面时 页眉页脚消失并在滚动停止时重新出现 有没有一种方法可以让它在您滚动时始终固定在屏幕上并显示 我只能想到一种方法是
  • C++:平台相关类型 - 最佳模式[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在头文件中使用声明

    我一直在寻找有关使用的一些说明使用声明在头文件中 我正在四处搜索 但无法完全得到我正在寻找的答案 到目前为止我的研究得出的结论是 将它们用于非全局的范围是好的 而命名空间指令则不好 我明白 至少我希望如此 所以在我的例子中我使用shared
  • Java 中的 HTTP 标头编码/解码

    自定义 HTTP 标头被传递到 Servlet 应用程序以进行身份 验证 标头值必须能够包含重音符号和其他非 ASCII 字符 因此必须采用某种编码 最好是 UTF 8 控制身份验证环境的开发人员向我提供了这段 Java 代码 String
  • 为什么 firefox/chrome 显示的页面与 IE8 不同?

    当我看着 我看到最新版本 with Firefox and Chrome 但是一个旧版本 with IE8 另外 通过屏幕抓取PHP Curl给我一个旧版本 我试过了CTRL 刷新在 IE8 中 但我无法让它向我显示最新版本 无论heade
  • 修复了左侧的侧边栏菜单和顶部的固定标题

    所以我想做的是一个固定的侧边栏 顶部有一个固定的菜单 中间的内容可以滚动 body html height 100 margin 0 aside background 90EE90 height 100 left 0 position fi
  • 如何像联系人应用程序一样在Android列表视图中绘制节标题?

    我知道如何在屏幕上显示它 但是当我在手机中使用 联系人 应用程序时 我发现当我滚动列表时 它的字母部分标题可以固定在顶部 如何做到这一点 请参阅此处的 AmazingListView 它是带有节标题的 ListView 它的工作方式与默认的
  • System.setProperty("sun.net.http.allowRestrictedHeaders", "true") 在詹金斯中不起作用

    我正在尝试在 http 请求标头中发送原始标头 但是当我获取其值时 我得到的是 null 而不是我在原始标头中设置的 url 另外 我还使用以下命令启用了受限标头作为詹金斯作业中请求标头的一部分发送 System setProperty s
  • 标题消息就像 Stack Overflow 中一样

    这是我第一次访问堆栈溢出 我看到了一条漂亮的标题消息 其中显示了文本和关闭按钮 标题栏是固定的 非常能吸引访问者的注意力 我想知道你们中是否有人知道获得相同类型标题栏的代码 快速的纯 JavaScript 实现 function Messa
  • JPEG 标头丢失/损坏

    我有一个 130kb jpeg 图像 无法在任何程序中打开 我需要修复它 从我使用的各种图像恢复软件中 我得到的只是 图像头损坏 丢失 当我查找文件的属性时 我什至没有得到任何信息 没有尺寸等 只有文件大小 一旦图像的标头丢失 是否可以恢复
  • 重定向后的 HTTP 响应代码

    有一个到服务器的信息重定向 一旦来自服务器的响应 我想检查 HTTP 代码以抛出异常 如果有任何以 4XX 开头的代码 为此 我需要知道如何从标头中仅获取 HTTP 代码 这里还涉及到服务器的重定向 所以我担心curl 对我来说没有用 到目
  • 生成 Java JNI 标头

    我想做的就是使用 JDK Javah exe 程序生成 JNI 头文件 但无论我尝试什么 我都会收到错误消息 错误 找不到 ddg ndkTest NativeLib 的类文件 其中 ddg ndkTest 是命名空间 NativeLib
  • 删除 PHP 中的标头

    为了允许缓存 PHP 生成的文件 我想确保 Pragma no cache 标头是not放 但是 如何删除可能已经设置的标头 这就对了could有可能 有人在代码中的某个地方写了header Pragma no cache 现在我想确保标头
  • 标题中的全日历自定义按钮

    我需要在同一页面上的两个 或更多 完整日历之间切换 并且希望将此功能添加到日历标题内的自定义按钮中 我在自定义按钮上发现了一些有趣的代码 但它有点过时 因为它引用的是 Fullcalendar v 1 6 1 而我正在使用 2 3 1 这是

随机推荐

  • FreeRtos任务通信之消息队列

    入队阻塞 xff1a 往队列写数据时 xff0c 队列满时的阻塞 当阻塞结束时 xff0c 优先级最高的任务优先进入就绪态 xff0c 同 优先级时 xff0c 阻塞时间最长的进入就绪态 出队阻塞 xff1a 读队列时 xff0c 队列为空
  • STM32F103C8T6 ADC功能

    12位逐次逼近型ADC 1us转换时间 输入电压0 3 3v和转化范围0 2 12 1 xff08 0 4095 xff09 成线性关系 2个ADC资源 xff0c ADC1和ADC2 xff0c 10个外部通道 有两种转换单元组 xff1
  • stm32串口实验

    目录 xff08 一 xff09 STM32 串口简介 二 软件设计 xff08 三 xff09 效果 xff1a 1 实现功能 xff1a STM32 通过串口和上位机的对话 xff0c STM32 在收到上位机发过来的字符串后 xff0
  • 基于stm32的GPS解析数据

    目录 1 GPS模块 2 GPS发送的数据格式 3 软件设计 3 1配置好串口 3 2然后写串口中断函数 效果 1 GPS模块 2 GPS发送的数据格式 GPRMC lt 1 gt lt 2 gt lt 3 gt lt 4 gt lt 5
  • 大疆遥控控制M3508电机二(基于HAL库)

    接上一篇文章 xff0c 话不多说直接开始 一 打开我们创建的工程文件 xff0c 先就建立一个文件夹用来存放我们写的子文件 xff08 不建立也行 xff09 xff0c 然后建立pid h xff0c pid c存入我们建立的文件夹中
  • aruco_ros 在相机图像中显示的坐标轴姿态与TF发布的姿态不一致 解决方法

    aruco ros 在相机图像中显示的坐标轴姿态与TF发布的姿态不一致 解决方法 运行环境问题描述解决方案 运行环境 系统版本 xff1a Ubuntu 16 04 ROS版本 xff1a Kinetic 问题描述 在进行手眼标定过程中 x
  • 安装vscode的时候没有勾选快捷方式用vscode打开文件,如何用vscode快速打开文件或者文件夹

    1 需要在注册表里面添加内容可以实现 xff0c 下面有一种简单的方式来完成这个操作 2 需要在电脑桌面新建一个Open File With VS code reg 文件然后用打开文件 xff0c 将以下代码复制 Windows Regis
  • C语言学习笔记->const和define区别

    1 define 是预编译指令 xff0c 而const 是普通变量的定义 define定义的宏是在预处理阶段展开的 xff0c 而const定义的只读变量在编译运行中使用 2 const定义的是变量 xff0c 而define定义的是常量
  • 基于栈、寄存器的优缺点

    基于栈的优点 xff1a 对硬件的依赖不高 xff0c 跨平台性 缺点 xff1a 使用的指令集高基于寄存器的优点 xff1a 相对于栈来说 xff0c 寄存器的性能高 xff0c 使用的指令集少 Java代码执行流程 xff1a java
  • Makefile文件的编写(实例详解)

    1 什么是Makefile xff1f 一个工程中的源文件不计其数 xff0c 其按类型 功能 模块分别放在若干个目录中 xff0c Makefile定义了一系列的规则来指定哪些文件需要先编译 xff0c 哪些文件需要后编译 xff0c 哪
  • 用C语言实现万年历的代码及思路(详细教程)

    万年历程序要求 xff1a 1 当选择1的时候 xff0c 输入年 xff0c 打印输入的这一年12月的日历 2 当选择2的时候 xff0c 输入年 月 xff0c 打印输入这一年这一月的日历 实现效果 xff1a 选择1时 span cl
  • 有符号数和无符号数参与运算时的问题

    陷阱题目 xff1a 下面的代码输出是 xff08 xff09 span class token macro property span class token directive hash span span class token di
  • 【Linux网络编程】基于UDP实现多人聊天室

    文章目录 一 UDP的概念1 1 UDP1 2 UDP特点 二 采用UDP实现多人聊天室原因三 多人聊天室项目功能四 实现多人聊天室项目流程分析4 1 前期准备4 1 1 定义结构体4 1 2 定义链表 4 2 多人聊天室服务器4 2 1
  • 【C++】C向C++的知识过度(上)

    文章目录 一 C与C 43 43 的区别1 1 C是面向过程的1 2 C 43 43 是面向对象的1 3 编译器的区别 二 C与C 43 43 默认代码的不同三 命名空间3 1 关键字 96 namespace 96 去定义自己的名字空间
  • 【C++】四种类型转换 | C++异常处理机制 | C++11新特性之右值引用和移动构造

    文章目录 一 C 43 43 中的四种类型转换1 1 静态类型转换1 1 1 C 43 43 中内置类型的转换1 1 2 C 43 43 中的有继承关系存在的场景下的类型强转 1 2 动态类型转换1 3 常类型转换1 4 解释类型转换 二
  • 【Linux操作系统】进程详解(上)

    文章目录 一 进程的定义二 进程的特征三 进程的组成及其作用四 进程控制块4 1 进程控制块定义4 2 task struct的内容 五 进程与程序的区别六 进程与线程的区别七 进程的种类八 PID8 1 PID定义8 2 特殊PID的进程
  • 【Linux操作系统】进程详解(下)

    文章目录 前言一 父子进程共用光标问题1 1 验证1 2 规避共用光标问题使用多进程拷贝同一个文件 二 进程相关函数2 1 getpid getppid函数2 2 exit exit函数2 3 wait waitpid函数 三 守护进程3
  • git补丁操作(git diff、git format-patch、git apply、git am)

    https blog csdn net qq 42138454 article details 119058431 实际使用补丁用的 xff1a patch p1 lt device nuwa diff 一 打补丁的两种方法 Git 提供了
  • 三、C++ 链接器 linker

    cilinking 从C 43 43 源码到可执行二进制的过程 compile文件之后进行链接 xff0c 找到每个符号 函数的位置 xff0c 并将其链接在一起 每个文件被编译成一个独立的 obj文件作为translation unit
  • 五、C++中的头文件 Header Files

    头文件 Header Files传统上用于声明某些函数类型 xff0c 以便可以用于整个程序中 例如 xff1a 在一个文件1中创建函数 xff0c 然后想在另一个文件2中使用 xff0c 尝试编译此文件2时 xff0c C 43 43 不