c++的头文件到底应该怎么写?

总结一下头文件的编写规则和注意事项:

  1. 头文件的作用是供其他的 .cpp 文件包含,它们本身不直接参与编译,但其内容会在多个 .cpp 文件中被编译。

  2. 头文件中应该只放变量和函数的声明,而不能放它们的定义。因为头文件的内容会被多个 .cpp 文件包含,如果放置定义,会导致同一个符号(变量或函数)在多个文件中被定义,违反了"定义只能有一次"的规则。

  3. 头文件中可以放置以下三种例外情况的定义:

    • const 对象的定义:因为全局的 const 对象默认没有 extern 声明,所以它只在当前文件中有效,不会导致多重定义。
    • 内联函数(inline)的定义:内联函数需要在编译时看到完整定义,且可以在程序中定义多次,只要在每个 .cpp 文件中只出现一次且定义相同。
    • 类(class)的定义:创建类对象时,编译器需要知道类的完整定义才能确定对象的布局。可以把类的定义放在头文件中,函数成员的实现代码放在 .cpp 文件中,或者直接将函数成员的实现写进类定义中。
  4. 为了防止头文件被同一个 .cpp 文件多次包含导致的问题,可以使用头文件保护措施,即通过 #define 定义一个名字,并使用条件编译指令 #ifndef…#endif,让编译器根据这个名字是否被定义来决定是否继续编译头文件中的内容。

  5. 在编写头文件时,要特别注意使用头文件保护措施,以避免多重包含导致的编译错误。

总之,头文件的编写需要遵循一定的规则,合理划分声明和定义,并且要注意使用头文件保护措施。遵循这些规则和注意事项,可以有效避免头文件在多个 .cpp 文件中包含时导致的编译和链接错误。


当你在头文件中写下像 int a;void f() {} 这样的语句时,实际上是在定义变量或函数,而不仅仅是声明。如果这个头文件被多个源文件包含,那么每个源文件都会有一个变量 a 或函数 f 的定义。在编译阶段,每个源文件都会独立编译,生成对应的目标文件(.o或.obj文件)。

问题出现在链接阶段。当链接器尝试将所有目标文件合并成一个可执行文件或库文件时,它会发现有多个 a 变量或 f 函数的定义。这违反了C++的一个规则:一个变量或函数只能有一个定义(One Definition Rule,ODR)。因此,链接器会报错,指出存在重复的符号定义。

为了避免这个问题,我们通常在头文件中只包含变量或函数的声明,而将它们的定义放在对应的源文件中。声明的作用是告诉编译器这个符号的存在,以及它的类型和签名等信息。而定义则提供了符号的实际内容或实现。

例如,在头文件中,我们可以写:

// MyHeader.h
extern int a;
void f();

然后在对应的源文件中提供定义:

// MySource.cpp
#include "MyHeader.h"int a = 42;
void f() {// 函数的实现
}

通过这种方式,我们可以在多个源文件中包含同一个头文件,而不会导致重复定义的错误。编译器会在编译每个源文件时使用头文件中的声明,而在链接阶段,链接器会找到变量 a 和函数 f 的唯一定义,并正确地生成最终的可执行文件或库文件。

这就是为什么我们通常遵循这样的规则:在头文件中只写声明,而在源文件中写定义。这有助于避免由于重复定义而导致的编译和链接错误。

参考链接:https://www.cnblogs.com/lidabo/archive/2012/04/17/2454568.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/57420.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

几何算法系列:空间实体体积计算公式推导

1.前言 面积和体积的计算是常见和基础的几何算法话题,面积和体积通常作为面或构件的基本信息参与相关的建模、计算、分析等过程。 有关面积的计算,可以参考博主此前的文章, 一种误差较小的轮廓面积计算算法_轮廓面积计算原理-CSDN博客文章…

设计模式——装饰者模式(8)

一、定义 指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。我们先来看一个快餐店的例子。快餐店有炒面、炒饭这些快餐,可以额外附加鸡蛋、火腿、培根这些配菜,当然加配菜需要额…

arp代答观察

文章目录 代答和代理简述实验前提先不开启proxy代答的配置开启代答总结 代答和代理简述 ARP(地址解析协议)是在局域网中用于将IP地址映射到MAC地址的协议。在理解 ARP 代答和 ARP 代理之前,让我们先澄清一下 ARP 的基本工作原理。 ARP 代答&…

鹏哥C语言81-82---指针和数组+二级指针+指针数组

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> //--------------------------------------------------------------------------------------------------------5. 指针和数组 数组&#xff1a;一组相同类型元素的集合 指针变量&…

在 VS Code 中轻松绘图:Draw.io Integration 插件详解

文章目录 在 VS Code 中轻松绘图&#xff1a;Draw.io Integration 插件详解一、什么是 Draw.io Integration 插件&#xff1f;二、插件安装指南1. 安装步骤2. 配置插件 三、如何使用 Draw.io Integration 插件&#xff1f;1. 创建新绘图文件2. 编辑现有图表3. 常用功能与技巧 四…

中小型医院网站:Spring Boot框架详解

5 系统实现 5.1 用户功能模块的实现 用户进入本系统可查看系统信息&#xff0c;包括首页、门诊信息、药库信息以及系统公告信息等&#xff0c;系统前台主界面展示如图5-1所示。 图5-1系统前台主界面图 5.1.1用户登录界面 用户要想实现预约挂号功能&#xff0c;必须登录系统&a…

QGraphics类型学习使用【Qt】【C++】

QGraphics类型学习使用 需求过程全部完整代码 首先已知&#xff0c;QGraphicsView&#xff0c;QGraphicsScene, QGraphicsItem&#xff0c;分别称为&#xff1a;视图&#xff0c;场景&#xff0c;图元&#xff0c;图表就是各种各样的元素&#xff0c;图片元素&#xff0c;线条元…

k8s部署Kafka集群超详细讲解

准备部署环境 Kubernetes集群信息 NAMEVERSIONk8s-masterv1.29.2k8s-node01v1.29.2k8s-node02v1.29.2 Kafka&#xff1a;3.7.1版本&#xff0c;apche版本 Zookeeper&#xff1a;3.6.3版本 准备StorageClass # kubectl get sc NAME PROVISIONER RECLA…

股价创52周新高,云顶新耀成为“黑马”的启示录

踏入2024年以来&#xff0c;创新药产业持续释放积极信号。今年本土创新药出海交易额已超200亿美元&#xff0c;最近医保续约和谈判也有望促进国内创新药长期放量。 市场预期转好之下&#xff0c;生物医药板块在新一轮牛市中进入了估值修复的阶段。HSHKBIO&#xff08;恒生香港…

【LVGL快速入门(二)】LVGL开源框架入门教程之框架使用(UI界面设计)

零.前置篇章 本篇前置文章为【LVGL快速入门(一)】LVGL开源框架入门教程之框架移植 一.UI设计 介绍使用之前&#xff0c;我们要学习一款LVGL官方的UI设计工具SquareLine Studio&#xff0c;使用图形化设计方式设计出我们想要的界面&#xff0c;然后生成对应源文件导入工程使用…

openssh openssl zlib 升级至最新版解决安全问题

openssl依赖于zlib&#xff0c; openssh依赖于openssl和zlib&#xff0c; 所以我们要先安装zlib&#xff0c;然后是openssl&#xff0c;最后是openssh。 各软件下载地址&#xff1a; zlib 地址&#xff1a; zlib Home Site openssl 地址&#xff1a; Downloads | Library…

C#从零开始学习(接口,强制转化和is)(7)

有时根据对象能做什么来分组,而不是根据他们继承的类.这就引入了接口 让无关的类做相同的动作 接口定义一个类必须实现的方法和属性 一个类实现一个接口时,必须包含接口中列出的所有方法和属性 向下强制转化 Appliance是CoffeeMaker的基类 Appliance powerConsumer new Co…

时空智友企业流程化管控系统uploadStudioFile接口存在任意文件上传漏洞

免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. 时空智友…

【密码分析学 笔记】ch3 3.1 差分分析

ch3 分组密码的差分分析和相关分析方法 3.1 差分分析 评估分组密码安全性通用方法可用于杂凑函数和流密码安全性 预备知识&#xff1a; 迭代性分组密码&#xff08;分组密码一般结构&#xff09;简化版本 mini-AES CipherFour算法 3.1.1 差分分析原理 现象&#xff1a;密…

JMeter使用不同方式传递接口参数

1、使用 HTTP 请求中的参数&#xff1a; 在 JMeter 的测试计划中&#xff0c;添加一个 "HTTP 请求" 元件。 在 "HTTP 请求" 元件的参数化选项中&#xff0c;可以添加参数的名称和值。可以手动输入参数&#xff0c;也可以使用变量来传递参数值。 如果要使…

汇川机器人与PLC通信-ModbusTCP超详细案例

#SCARA机器人与H5UPLC通过ModbusTCP通信,HMI界面手动操作# 应用背景: 本项目案例部分软件界面已被更新,如机器人示教软件旧版本S01.19R03。但通信的原理基本一致,废话少说,我们直接上图。 一、PLC端配置 1.添加ROB通讯表(自定义),变量表内容包括ROB系统变量,IN区和…

【利用Seaborn进行高级数据可视化】创建美观且信息丰富的图表!

利用Seaborn进行高级数据可视化&#xff1a;创建美观且信息丰富的图表 数据可视化是数据分析和科学研究中不可或缺的部分。通过有效的图表&#xff0c;我们可以迅速了解数据的分布、趋势和关系。在Python的数据科学生态系统中&#xff0c;Seaborn是一个基于Matplotlib的高级库…

大厂面试真题-了解云原生吗,简单说一下docker和k8s

K8s&#xff08;Kubernetes&#xff09;和Docker都是容器化技术中的关键组件&#xff0c;但它们各自扮演着不同的角色。以下是对这两者的详细解析&#xff1a; 一、Docker Docker是一个开源的容器化平台&#xff0c;它允许开发人员将应用程序及其依赖项打包为一个独立的镜像&…

条款8 优先考虑nullptr而非0和NULL

目录 一、nullptr,0,NULL都是什么类型 二、正确调用函数指针版本的函数重载 三、模板推导时使用不能混用 一、nullptr,0,NULL都是什么类型 auto a = 0; -> int auto a = NULL; -> long auto a = nullptr; -> std::nullptr_t 二、正确调用函数…

Notepad++将搜索内容所在行选中,并进行复制等操作

背景 Notepad在非常多的数据行内容中&#xff0c;按照指定内容检索&#xff0c;并定位到具体行&#xff0c;而后对内容行的数据进行复制、剪切、删除等处理动作。 操作说明 检索并标记所在行 弹出搜索框&#xff1a;按下 Ctrl F。 输入查找字符串&#xff1a;在搜索框中输入要…