C++笔记: 定义,声明,头文件及其他

Windows下用VScode编写C++程序如何添加并应用自定义头文件 Windows下用VScode编写C++程序如何添加并应用自定义头文件 关键词:Windows,CPP,VScode,自定义头文件 一个编程小白,正在试着用vscode学CPP,标准库应用没有问题,但自定义的头文件和自定义头文件中声明的函数用不了。刚刚被这个问题整个半死,花了一晚上终于解决了。 整体如下 main函数引用了一个include文件夹中自定义的.h文件,并在lib文件夹里有相应.cp... 阅读详情

首先必须区分各种对象(这里的“对象”是一个广义的说法,它包括变量、函数、类等等东西)的定义(definition)和声明(declarition)。下面来分如下几种主要情况讨论:

1. 函数

我觉得这是一种最容易理解的情况。函数的声明就是函数原型,函数的定义就是函数的具体实现。编译器在遇到一个函数调用语句时,必须知道这个函数的原型以进行相应的类型检查,因此必须把该函数的声明(当然定义也可以,因为在此时定义隐含了声明)放在前面。

只要是比ACM题目那种一百行左右代码再大一点的项目,一般都不会把所有代码写在一个文件里。注意编译器的执行过程是分两步的,首先把每个.cpp文件(或者.c, .cc等等)分别编译成目标文件(通常是.o, .obj等等),然后再用链接器把目标文件组装成一个可执行文件。注意“分别”两字,也就是说,编译器必须能够不依赖其他cpp文件就可以把当前的cpp文件编译成目标文件。

我们先不考虑类等等内容,假设现在我实现了一系列逻辑上有一定关联的工具函数,为了清楚起见我把它们放在同一个util.cpp文件里,而把使用这 些工具函数的其他代码放在文件main.cpp里,那么要编译main.cpp,必须知道里面用到的工具函数的原型,所以必须在main.cpp里有一份 该函数的声明(只需要声明就够了,编译器可以据此生成压栈、取返回值等等汇编代码,至于函数内部的实现代码是在util.o目标文件里,等链接的时候组装 在一起就可以)

然而,当有多个cpp文件都要用到这些工具函数时,如果我们每次都要在cpp文件前面附加一堆函数声明的话,就显得有点太啰嗦了。于是头文件就派上用场了。这时惯常的做法是把util里(想提供给外界使用的)函数的声明放在.h头文件里,如果另外的cpp文件要用到某个函数,只要把对应的头文件include进来即可。注意一定不要把函数的定义放在头文件里,否则的话,如果这个头文件被包含进多个cpp文件里,在链接时就会出现函数重定义的错误。也就是说,函数可以声明多次,但只能定义一次(有一个例外下面会提到)。

另外一点是,如果不想某个文件里的函数被外面看到,应该用static修饰。应该只开放那些想公开的函数,并把想公开的函数的声明放到对应的头文件里。

这里再插一句,头文件只是为了方便程序员,编译器是看不到头文件的,把include的文件插入到相应的位置之类的事情都是预处理器完成的。头文件不必有对应的.cpp文件,不必是.h扩展名,实际上它可以是随便什么东西,只要你愿意就好,编译器根本不care。

关于头文件还有一点,如果我们不小心的话,经常会出现同一份头文件被包含了多次的情况(有时候可能是不可避免的)。比如我自己写了一个 roba.h,里面有一句#include <string>,又写了一个main.h,里面即include了roba.h,又include了<string>,这样 string就被包含了两次。这样就有可能出现重复定义(因为头文件里不止有函数声明,还有比如类的定义),这时我们可以用#ifndef这个东西控制这 个头文件的内容只被包含一次。常见写法如下:

  #ifndef _ROBA_H_
  #define _ROBA_H_
  //...
  //the body of roba.h
  //...

  #endif

最后再说一下inline函数,这是一个特例,inline函数的定义应该写在头文件里。因为编译器要内联这个函数,就必须知道函数的实现,不然的话是无法单独编译出一个目标文件的。对inline函数不必担心重定义的问题,它可以看作局部于所在的源文件的。


2. 变量

这里主要是讨论全局变量的使用,对于局部变量(即在函数内部定义的,在栈上分配空间的变量)不予考虑。全局变量的情况与前一篇说的函数的情况类似,但是更迷惑人一些。全局变量的定义是在所有函数的外面,比如下面语句:

  int roba;

定义了一个叫做roba的int型全局变量。而全局变量的声明是这样:

  extern int roba;

全局变量与函数一样要求,定义只能一次,声明可以多次,在使用前编译器必须看到声明。如果多个源文件要共享一个全局变量,初学者常犯的错误有两种: 一种是在多个文件中都写了int roba;,这样会导致链接时发生重复定义的错误;另一种是只在一个文件中写了int roba;,以为在其他的文件的文件中可以直接用,但实际上因为在其他文件中没有对这个全局变量的声明,所以会发生编译错误。正确的写法是,在某一个文件 中用int roba的形式定义,而在其他用到该变量的文件中用extern int roba的形式声明。

如果要把变量放到头文件里,从前面的讨论可以看出,一定不要把int roba;这样的定义放进去(因为这样的话如果这个头文件被包括进多个cpp文件就会产生重复定义),而应该写extern int roba;这样的声明,然后在某个cpp文件中定义int roba; 。

与函数类似,如果我们不想其他的文件看到某个全局变量,也可以用static修饰它,表示它的作用域局部于此文件内。(注意我说的不是static的局部变量)

下面又开始说特例了。对于这种写法:

  extern int roba = 1;

是被当作定义而不是声明的,尽管加了一个extern。

另外一个要注意的是const型的全局对象,它默认是局部于文件的,也就是说默认就是static的。这是因为C++允许(并且鼓励)这样的写法:

  const int N = 100;
  int loli[N];

我们可以看出,编译器必须知道N的值以后,才能确定loli数组的大小并生成相应代码。所以如果像非const的全局变量一样,把const int N定义在别的文件里,编译器就没办法在编译时知道它的值,也就不能单独编译这个cpp文件,这就违反了上次说的那个要求。基于这个考虑,C++规定const全局对象是局部于文件的,也就是说我们可以安全地把 const int N = 100; 这样的东西放在头文件里,不会出现重定义。

我们也可以用extern const int N = 100;这样的写法强制使其全局可见,在其他的文件中用extern const int N;来进行声明,但我认为这样会产生不必要的混乱,对程序效率也并没有提升。可能有人会觉得如果在每个文件里声明一个局部于本文件的全局const对象会 浪费空间,但实际上编译器基本都会把这个const优化掉的,产生的效果和古老的 #define N 100 宏定义是一样的。

(待续)

CPP {extern声明, 头文件里的extern声明, 头文件的防重复包含的宏定义} 1 阅读详情

相关推荐

LoRa双端通信稳定性核心:同步字配置与LLCC68工程实践

LoRa是一种基于扩频调制的远距离低功耗无线通信技术,其物理层鲁棒性依赖于发射端与接收端在频率、带宽、扩频因子及同步字等关键参数上的严格一致。同步字作为LoRa帧结构中位于前导码之后的2字节标识字段,承担着物理层帧过滤与网络隔离的核心作用,直接影响通信成功率与抗干扰能力。在实际嵌入式开发中,尤其采用LLCC68等专用射频芯片时,同步字配置错误或双端不一致是导致‘能发不能收’‘间歇性丢包’等典型问题的首要原因。本文面向STM32等Cortex-M平台开发者,结合硬件一致性约束、驱动移植方法论与寄存器级调试手段

weixin_36019375的博客 130

在源文件(.c)和头文件(.h)中声明和定义的区别——C语言

https://www.cnblogs.com/lanhaicode/p/10686688.html https://www.cnblogs.com/lanhaicode/p/10546514.html 最近在看多文件编程的时候遇到的一个问题,本来以为理解了声明和定义的区别(然而并没有····),也算是重新认识了一次声明和定义,下面上代码 声明和定义:有分配空间的叫定义,没分配空间的叫...

happylzs2008的专栏 1389

机器人轨迹规划——梯形速度轨迹(超详细)

机器人轨迹 这一系列轨迹教程将主要包括以下内容: 点到点轨迹(P2P) 五次多项式插值轨迹 三次多项式插值轨迹 梯形速度曲线轨迹 双S形速度曲线轨迹 多个自由度轨迹的时间同步 在线轨迹规划 多项式在线轨迹规划 梯形在线轨迹规划 双S形在线轨迹规划 非线性实时轨迹滤波 多点轨迹(Multi-point) 三次样条曲线(cubic spline) 贝赛尔曲线(Bezier Curve) B样条曲线(BSpline) 时间最优轨迹 三次样条时间最优轨迹 任意路径下的时间最优轨迹 时间

出门搔白首,若负平生志 1万+

C/C++:头文件与cpp文件的声明/定义

一、头文件 1、 一般来说,头文件仅仅用于声明,相应的定义要放在对应的cpp文件中。  声明的内容一般可以是:1. 类定义体;2.类中的成员方法; 3. 类外的函数; 4. 类外的变量;5. 类型。   一个文件(比如main.cpp)包含(#include)了一个头文件(比如item.h),就相当于声明了Item.h中声明的所有内容。 2、但是const常量,inline函数,static函数...

yongjunhe的专栏 5488

AWS DevOps Agent 完全指南

AI 驱动的 SRE 队友,7×24 自主调查告警、定位根因、生成修复方案、预防未来故障。

探索云原生与智能化驱动下的安全运维新范式。关注DevSecOps、可观测性、AIOps等前沿领域,与您共赴技术前沿。 381

《爬虫和逆向教程》 - 专栏介绍和目录

本专栏为爬虫初学者和进阶开发者量身定制的爬虫和逆向学习园地。为你提供全面而深入的爬虫和逆向技术指导,从入门到精通,从基础理论到高级实战,助你在数据的海洋中畅游,挖掘出有价值的信息。通过本专栏的学习,你将具备独立开发和优化爬虫程序的能力,及逆向分析能力和项目开发能力,成为爬虫领域的佼佼者。

数据知道的博客 2万+

qt 全局变量需要先在头文件中声明,再在.cpp文件中定义。

在头文件中声明了一个qmap格式的全局变量,但是在使用的时候却遇到“无法解析的外部指令”的错误。

m0_46300139的博客 762

【2026年华为暑期实习(AI)-4月29日-第一题- 选择题】(题目+思路+Java&C++&Python解析+在线测试)

本文摘要涵盖了机器学习和深度学习中的多个核心概念与技术,包括非负矩阵分解、条件数、MobileNet创新点、LDA降维、大模型评测指标、半精度训练、多任务学习、GPU存储层次、正则化、张量并行等。通过12道单选题和8道多选题的形式,系统性地考察了相关理论原理、应用场景及工程实践要点。题目设计注重概念准确性(如LDA目标函数)、技术细节(如Megatron-LM的并行策略)与实际应用(如FP16训练动机),并包含概率统计(二项分布)和数值计算(微分误差分析)等数学基础内容,全面检验读者对AI领域关键知识的掌握

m0_73659489的博客 143

C| |头文件中为什么只声明不定义,而类定义又可以放在头文件中

头文件中为什么只声明不定义,而类定义又可以放在头文件中 首先要了解几个基本概念: 编译单元 对于c语言,每一个.c文件就是一个编译单元。仅仅从编译来说,各个编译单元之间没有联系   未解决符号表 提供了在该编译单元引用,但是定义不在本编译单元的符号的地址(拥有者是编译单元)   导出符号表 提供了本编译单元具有定义,而且可以提供给其他编译单元使用的符号和地址(拥有者是编...

凯的博客 3767

3、图像中文字信息提取技术全解析

本文全面解析了图像中文字信息提取(Text Information Extraction,TIE)的技术原理、挑战及应用领域。详细介绍了图像中三种主要文字形式:场景文字、字幕文字和文档文字的特点及提取难点。系统阐述了TIE技术的主要流程步骤,包括文字检测、定位、提取与增强、识别等关键阶段,并对主流技术方法进行了分类比较,包括基于连通组件、边缘、纹理等方法的优缺点分析。文章还介绍了多种其他提取技术,如二值化方法、混合方法、基于梯度的方法等,并提出了一种基于立体帧的新型场景文字提取方法,通过实验验证了该方法在召

ll5678的博客 119

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

关于头文件

<br />声明:本内容摘抄自网络 ,仅为了以后查看方便,特此声明。支持原创。<br />#include "xxxx.h" 这条语句的作用,就是把xxxx.h文件的所有内容插入到这条语句所在的地方然后编译器从上到下编译一个源文件明白了吧 也就是说 如果你在 a.h 里 include "b.h" 然后在 a.cpp 里 include "a.h" 那结果就是 编译器把 b.h 的内容放在 a.cpp 的最前面 ,然后把 a.h 的内容放在次前面,下面才到 a.cpp 的内容<br />相同点:<br />

小马过河的专栏 736

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

笔记26:C++在【namespace调用函数】/【源文件中定义函数,头文件声明调用函数】有何不同?

总结:标准库用来定义功能;命名空间用来定义实现标准库中的功能所要用到的函数+对象+变量;相当于第一行把以后要用的标准库引入,但是还不能直接使用标准库中定义的功能,还要把标准命名空间中的东西释放出来/使用std::引出来才行。第一行:用来通过头文件引入C++标准库第二行:用来将标准命名空间中的【函数+对象+变量】释放出来。

weixin_44063383的博客 302

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

C++头文件和cpp文件的原理

1 C++编译模式 通常,在一个C++程序中,只包含两类文件——.cpp文件和.h文件。 .cpp文件被称作C++源文件,里面放的都是C++的源代码 .h文件则被称作C++头文件,里面放的也是C++的源代码,头文件不用被编译 C++语言支持“分别编译”(separate compilation)。也就是说,一个程序所有的内容,可以分成不同的部分分别放在不同的.cpp文件里。.cpp文件里的东西都是相对独立的,在编译(compile)时不需要与其他文件互通,只需要在编译成目标文件后再与其他的目标文件做一次

呆呆象呆呆的博客 7513

C++ 在.h文件中包含头文件和在.cpp文件中包含头文件有什么区别?前置声明

Note:类A在编译的时候不需要拿到类B的定义是因为这里面定义的是指针,而对于指针是不需要定义就可以进行内存布局的,在编译A的类的声明的时候,在进行内存布局的时候是不需要拿到B的定义的。假设有两个类 A 和 B,A 类包含了 B 类的一个指针成员,并且在 A.cpp 文件中使用了 B 类的成员函数。6、如果a.c包含了头文件a.h,a.h包含了头文件b.h,b.c也包含了b.h,那么当b.h发生改变时,a.c和b.c都会重新编译。其中A类有一个成员b是Class B的指针,这个时候可使用类前置声明。

qq_40178082的博客 2538

C/C++头文件与变量的声明和定义

C/C++头文件与变量的声明和定义最近遇到了变量重复包含的问题,才发现自己有好多知识已经模糊了,真惭愧。首先说下头文件,其实头文件对计算机而言没什么作用,她只是在预编译时在#include的地方展开一下,没别的意义了,头文件主要作用有两个:一是把很多其他文件需要重复使用的函数变量等在此声明,在需要的地方include;二是给使用你函数文件的人看的。那既然是说明,那么头文件里面放的自然就是关于函数,变

祝 枫 2万+

C++中头文件中定义的变量

1、在头文件.h中定义static变量,如: static int x;其实就等效于每个引用该头文件的源文件中,定义一个变量名为x的整型静态全局变量,每个文件中的x变量均属于本源文件,各文件中的互不相同,作用域为引用头文件的源文件范围内 2、在头文件.h中定义变量,但是不初始化 int x; 相当于定义了一个全局变量x,同时在所有引用该头文件的.cpp文件中声明。作用域为整个项目(所有源文件); ...

qq_42681507的博客 1万+

头文件中只有声明,没有定义

前言: 头文件中只有声明,而没有定义。这是为什么呢?刚看到这个问题我也比较纳闷。因为我学C++之前一直是这样的,直到学习了C++中的内联函数,内联函数的声明和定义分别在不同的源文件中,出现了链接错误。这个时候又接触到了这个问题:头文件中只有声明而没有定义。在本篇博客中,我会分析这方面的内容,同时也会讲到内联函数。 目录 前言: 头文件声明和定义 《高质量C/C++编程指南》说明 内联...

你又来看我了,一起学习吧 1万+

C++笔记(十二)——头文件(.h)和源文件(.cpp)写法

        用C++编写比较大型的项目时,文件的分割管理确实确实是非常必要的 。下面就非常简洁明了地谈谈头文件(.h)和源文件(.cpp)应该怎么写。        在.h文件中,主要是进行类的定义,包括数据成员和函数成员的声明(成员函数的定义也可以在这个文件中进行),一般类的数据成员被声明为私有的,函数成员被声明为公有的。在.cpp文件中进行变量的赋值和函数的实例化。细分的话,通常main...

qq_37764129的博客 3万+

C++ 之头文件声明定义

最近在学习 c++, 在编译与链接过程中遇到了一些定义与声明的问题, 经过多处查阅资料, 基本解惑. 现记录与此, 希望让后面人少走些弯路. C++ 的头文件应该用什么扩展名? 目前业界的常用格式如下: implementation file *.cpp *.cc *.cc *.c header file *.hpp *.h++ *.hh *.hxx *.h 一句话: 建议 源文件使用 .cpp, 头文件使用 .hpp 关于 implementation file 并没有什么说的, 使用.

q752933833的博客 2957

C++中的声明、定义、头文件与源文件详解

声明向编译器介绍一个标识符(变量、函数、类等)的名称和类型,但不分配存储空间或提供实现。// 变量声明// 声明一个整型变量// 声明一个浮点变量// 函数声明// 类声明(前向声明)声明的特点仅告诉编译器标识符的类型和名称不分配内存(对于变量)不提供实现(对于函数)可以在同一编译单元中重复多次通常使用extern关键字明确表示变量声明定义不仅告诉编译器标识符的存在,还会分配内存(对于变量)或提供实现(对于函数和类)。// 变量定义// 定义并初始化一个整型变量。

kanhao100的博客 1989

C++ 在一个cpp文件中使用另一个cpp文件中定义的函数

C++ 在一个cpp文件中 使用另一个cpp文件中定义的函数建立一个console项目头文件cpp文件main.cpp 建立一个console项目 以dev为例,在【文件】【新建】【项目】,新建一个console项目。 头文件 添加新文件,输入说要使用函数的声明,保存为.h文件。 int add(int a,int b); cpp文件 定义在.h中声明的函数,保存为.cpp文件。 #include<iostream> #include"chen.h"//不要忘记这个 int a

m0_43456002的博客 9263

C++声明与定义以及初始化,头文件的书写规范

初始化 初始化:当一个对象被创建的同时获得了特定的值。 1.初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值代替; 2.默认初始化:如果定义变量时没有指定初值,则变量被默认初始化,也即编译器给定了一个默认值,该默认值由数据类型和定义的位置决定; 3.显式初始化:即定义变量时给定初始值; 4.绝大多数类都支持无须显式初始化而定义对象,这样的类提供了一个合适的默认值,但是对于内置类型需要格外注意定义的位置; 内置类型变量的初始化 当内置类型变量在定义时没有

人工智蟑的博客 4431

C++声明与定义,头文件

extern int i; //声明i而非定义i int j; //声明并定义j; extern double pi = 3.14; //定义(包含显式初始化的声明即为定义) //在函数体内,如果试图初始化一个由extern标记的变量,将引发错误 //变量只能被定义一次,可被声明多次 头文件 //头文件 类的定义,外部变量的声明,函数的声明,只能写声明不能写定义(类的定义和const...

zm_1900的博客 2942

头文件中只能声明变量不能定义变量 而声明变量必须带extern,为什么头文件中变量的声明都没有加

1.头文件中不可以放变量的定义!一般头文件中只是放变量的声明,因为头文件要被其他文件包含#include,如果把定义放在头文件的话,就不能避免多次定义变量。C++不允许多次定义变量,一个程序中对指定变量的定义只有一次,声明可以无数次。 三个例外:1)值在编译时就已知的const变量的定义可放在头文件中,如:const int num=10; 2)类的定义可放在头文件中。 3)inline函数。 2.定义和声明是不同的。定义只能出现一次,而声明可以出现多次。 下面的语句是定义,不能放在头文件中: extern

qq_41841073的博客 3561
上一篇: 清除VS2010最近打开记录脚本
下一篇: C# 两种启动bat文件方法的区别——关键在于进程的工作目录
656-3
博客等级 码龄12年 30粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值