关于前置声明

c++之类的前置声明分析 这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 1、 概念 (1)、类a声明中需要类b的类型,类b的声明中需要类a的类型 (2)、a类中的.h文件中包含b.h,类b的.h文 阅读详情

在计算机编程中,一个前置声明是指在程序员尚未给出完整定义之前对一个标示符(一个类型、一个变量或者一个函数)的声明。一个很简单的例子就是我们在函数A中使用了函数B,但是函数B的声明在函数A之后,这个时候,就需要对函数B进行前置声明,实际上就是在函数A之前提供一个函数B的原型(prototype)。这种现象其实在C语言编程中我们已经习以为常了,在C++中亦是如此,只不过在编写较大规模程序的时候,由于定义了较多的类,而这些类之间有可能是互相依赖的,换言之,类与类之间会互相引用,包括对成员函数的引用等等。笔者也经常在编写复杂程序的过程中遇到类似的问题,以下从一个简单例子出发,对此问题加以简要阐述,以为未来参考之需。

示例代码:

test1.h:
#ifndef test1_INCLUDED
#define test1_INCLUDED
class C1;
#include "test2.h"
class C1{
    .......
    void func1(C2* c2){
//     c2->func2();
     }
};
#endif

test2.h:
#ifndef test2_INCLUDED
#define test2_INCLUDED
class C2{
    .......
    void func1(C1* c1){
 //   c1->func2();
     }
};
#endif

test.cxx:
#include "test1.h"
int main(){
      C1 inst_c1(...);
      C2 inst_c2(...);
      ......
      return 0;
}

       两个头文件中的类存在互相引用,编译器在预处理过程中将头文件的内容include到源文件中,而头文件是按序include的,test.cxx包含头文件test1.h,而在包含test1.h之前,首先将test2.h包含进来,因此在最终的与处理之后的源文件中,类C2定义在C1之前,而C2用到了未被声明的类C1。因此在包含test2.h之前先对类C1进行前置声明,以避免编译时出现变量在作用域内未声明的错误。反之如果在源文件中包含的是test2.h,也需要在test2.h中包含test1.h,同时在包含头文件之前前置声明类C2。前置声明时还需注意一些小细节,例如声明的是一个类模板的话,需要将类模板的完整原型加上。

      前置声明的目的是告诉编译器这个标示符(包括变量或者函数等)虽然现在还没有定义,但是后面会有的;未定义全也就表示标示符的size是未知的,所以一般在前置声明之后具体定义之前,使用的都是该标示符的指针,如类要定义成指针类型,因为类大小虽然不确定,但是类指针的大小和所有指针一样,基本上都是四个字节,大小是确定的。另一方面,这样的用法这也就意味着前置声明实际上是有限制条件的,如果在当前代码中加入被注释的粗体部分的代码,编译时会发现如下错误:

test2.h: In member function ‘void C2::func1()’:
test2.h:19: error: invalid use of undefined type ‘struct C1’
test1.h:5: error: forward declaration of ‘struct C1’
test2.h:20: error: invalid use of undefined type ‘struct C1’
test1.h:5: error: forward declaration of ‘struct C1’

编译器能找到未定义类的前置声明信息,但是不能确定该类定义中的具体信息,例如成员函数,导致"invalid use"。这种情况下较好的解决方案是将涉及具体定义的部分移到源文件中,例如将类的成员函数定义在源文件中(注意添加inline修饰符),类的定义在头文件中已经包含,所以所有类的定义都是完整的。


小结:前置声明是在编程实践中经常会用到的一个手段,一定程度上克服了include头文件这种方式的弊端。出于避免重复包含头文件以及循环包含等问题,编程中会用宏来控制头文件的包含关系,而在某些情况下,包含头文件是无法解决声明的问题的,例如我们上述简单示例中,在test2.h中已经无法再include头文件test1.h了,因为后者的宏已经打开,即使没有宏控制,也会导致两个头文件循环包含的问题。这种情况下,前置声明就变得很有用。

           前置声明不能包治百病,在前置声明和具体定义之间的涉及标示符(变量、类、函数等等)实现细节的使用都是非法的,会导致编译错。所以好的编程习惯还是尽量将具体定义放在源文件中;另外,尽量不要在头文件中包含头文件,对于在大型工程中扩展模块功能有其如此,在原有头文件中添加新的头文件往往会导致示例代码中的问题,因为原有头文件可能会被多个其他的文件包含,牵一发而动全身,在源文件中做的所有扩展专属当前的源文件,不会影响到原有代码的其他部分。








        
Altium AD20的PCB板框绘制、定义板子形状、重新设置原点、放置尺寸标注 AD20的板框绘制与以前的版本不同,以前板框是在KeepOut层,而在AD20中没有这个层,绘制板框需要到机械层Mechanical1。 板框大小评估 首先进行板框大小评估。 工具 - 器件摆放 - 在矩形区域摆放。 之后通过鼠标框选矩形区域,元件会自动按照框选的范围进行摆放。这个操作可以重复多次,最后大致得出需要的板框尺寸。确定好后右键。 板框绘制,重新定义板子形状 点击下方的 Mechanical1,切换到机械层。放置线条,根据元件摆放来绘制PCB大致的形状,将元件完全包裹。 阅读详情

相关推荐

保姆级教学:从0搭建微信小程序SpringBoot+Vue(一)

目标:实现一个微信小程序从后端数据库MySQL获取的商品展示页。 框架:后端采用SpringBoot,前端采用Vue,数据库MySQL。 部署工具:IntelliJ IDEA 2024.2专业版+HbuilderX+Node+微信开发者工具,jdk1.8已安装

weixin_44545610的博客 4926

前置声明(Forward declaration)

前置声明是指声明一个类或结构体而不定义它,比如:class A;struct B;在声明之后,定义之前,该类或结构体被称为不完全类型(incompletion type),意思是,知道类型A和B,但不知道他包含哪些内容不完全类型的使用有一些限制,不如不能用它来定义对象,但可以定义指象该类型对象的指针,比如不但定义 A  a; B b;,但可以定义A* a;B *b;。原因是因为编译器不知道A和B有多大,所以无法构造对象,但是指针的类型是确定的4个字节,编译器就可以构造

李豪 Linux C++ 2215

从理论到实践:全面解析Cmk(设备能力指数)的应用与优化

本文全面解析了设备能力指数Cmk的核心概念、计算逻辑与关键应用场景。Cmk作为衡量设备本身固有加工能力的黄金标准,在设备验收、大修后验证及过程能力根因分析中至关重要。文章通过实战案例,详细阐述了执行Cmk测试的“五大固定”黄金法则、数据计算分析方法,并提供了Cmk不达标时的系统性排查与优化策略,帮助制造企业实现预防性质量管理。

jump7的博客 526

c++中前置声明和#include

c++中前置声明和#include 能用前置声明的尽量用前置声明,尽可能的避免用#include头文件 尽量在cpp文件中包含头文件,而非在头文件中 头文件相关 若.h文件和cpp文件不在解决方案里:位于其文件中,单独的引用到.h文件会报“error LNK2019:无法解析外部符号”的错误,但是单独引用.cpp文件就可以,include是吧对应的代码直接拷贝过去 当.h文件和.cpp文件没有在工程的解决方案里时,#include就是纯粹的拷贝和复制文件 源码编译过程: 远程序->预处理->

xiaofeilongyu的博客 1513

Python RPA 流程自动化快速上手

Python RPA 流程自动化快速上手

看花容易绣花难 1万+

奥比中光Dabai深度相机SDK在Ubuntu22.04的兼容性安装指南

本文详细指导如何在Ubuntu22.04系统上安装奥比中光Dabai深度相机的SDK。针对新旧版本不兼容的核心问题,重点推荐使用经过验证的v1.10.18版本SDK,并提供了从系统依赖检查、SDK下载安装、Python环境配置到编译测试的完整步骤,帮助用户成功解决安装难题并实现相机驱动。

j2k3l4的博客 1001

C语言的前置声明

另外需要注意的是当typedef定义的别名需要前置声明时,需要按照如下的方式进行声明,而不能直接写成 class 类别名 的形式。前置声明主要用于类与类之间的循环引用,且只是针对类型指针有效,对完整的类字段无效。提示类C是个不完整的类型,将其改为C*c即可通过编译。

qq_15054345的博客 928

VFIO框架源码分析(一)- 从初始化到设备访问

本文深入剖析了Linux内核中的VFIO(Virtual Function I/O)框架,详细解读了其从初始化到设备访问的全过程。VFIO通过Container->Group->Device的层次化设计,利用IOMMU提供安全隔离,允许用户空间直接访问物理设备。文章基于Linux v5.15版本,重点分析了vfio_init模块入口、Container创建与配置、Group关联以及最终设备访问等关键环节,揭示了VFIO如何通过逐层授权机制构建安全可靠的设备直通模型,为虚拟化技术提供核心支持。

qq_36071928的博客 380

C/C++编程:前置声明

什么是前置声明 一般的前置函数声明 #include <iostream> using namespace std; void fun(char ch, int *pValue, double dValue); void main() { int nValue = 100; double dValue = 111.22; fun('a', &nValue, dValue); system("pause"); } void fun(char ch, int

OceanStar的博客 2405

基于PLC的全自动洗衣机控制系统+控制程序

本设计使用PLC控制系统替换了传统的继电器控制系统,实现了全自动洗衣机在硬件方面的提升,丰富了全自动洗衣机在软件方面的功能,提高了全自动洗衣机的洗衣效率,基本可以满足用户的洗衣需求。

zzzz114231的博客 8957

如何通过Davinci Configurator来新增一个BswM仲裁规则

详细介绍如何通过Davinci Configurator来新增一个BswM仲裁规则。

initiallizer的博客 772

Qt 中类的 前向声明 和#include的区别

Qt 中类的 前向声明 和#include的区别

ken2232的博客 617

基于Simulink的无迹卡尔曼滤波(UKF)SOC高精度估计仿真

本文介绍了基于Simulink的无迹卡尔曼滤波(UKF)在电池SOC高精度估计中的应用。通过无迹变换替代传统EKF的线性化过程,UKF显著提升了SOC估计精度,在强非线性工况下误差可控制在0.5%以内。文章详细阐述了UKF的核心原理,包括Sigma点生成、状态预测和观测更新等关键步骤,并基于Thevenin等效电路模型构建了完整的UKF SOC估算系统。通过Simulink建模和仿真验证,展示了UKF在大电流脉冲、变温工况等复杂场景下的优异性能,其动态响应时间小于30ms,长期累积误差低于0.7%。研究为储

amy_mhd的博客 125

c++ 前置声明

#pragma onceclass bar; class foo { public: Bar getBar(); private Bar* _bar; }; 即:在.h文件中用class 声明代替include头文件 前置声明只能作为指针或引用,不能定义类的对象,自然也就不能调用对象中的方法了。 前置声明要求: 1.其声明的类是文件所声明的类的数据成员时,是指针成员或引用成员(而不是对象成员); 2.其声明的类是文件所声明的类的成员函数的参数或返回值时,该函数在文件中不存在定义。 ...

baidu_16370559的博客 4770

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

计算机控制技术及应用

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

C++的前置声明

当两个类相互包含头文件(嵌套)时使用前置声明,其他情况下尽量避免使用前置声明。 前置声明要求其为数据成员类型时为指针,其为函数参数或返回值类型时不出现该函数的定义。静态数据成员的类型可以不为指针。

19264389271的博客 7812

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

【C++】前置声明

讲一个工作期间遇到的C++知识点,关于前置声明的。

矢车菊二十七号 845

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

【c++】前置声明

前置声明只告诉编译器某个类的存在,但没有提供类的定义。因此,不能直接创建该类的对象或访问其成员。

cxyhjl的博客 1645

C++之类的前置声明

文章目录什么是前置声明为什么要引入前置声明前置声明的应用场景怎么使用前置声明前置声明的优点前置声明的缺点 什么是前置声明 前置声明(Forward Declaration),顾名思义,就只是一个声明,并不包含其定义。 为什么要引入前置声明 试想一下,如果需要在头文件A.h中使用另一个头文件B.h中的类B,有哪些做法? 1.把类B直接挪到A.h中(完全不推荐) 2.在A.h中包含B.h(写法为#in...

u012043391的专栏 2207

【C++】C++中前置声明的应用与陷阱

前置声明的使用 有一定C++开发经验的朋友可能会遇到这样的场景:两个类A与B是强耦合关系,类A要引用B的对象,类B也要引用类A的对象。好的,不难,我的第一直觉让我写出这样的代码: // A.h #include "B.h" class A { B b; public: A(void); virtual ~A(void); }; //A.cpp #include...

好习惯成就伟大 1万+

C++ 前置声明

问题 最近遇到了两个类A、B相互调用的情况,于是想当然的在两个类A和B的头文件中 #include 了所需的头文件,当然结果编译报错了。为什么呢,A需要B,B需要A,形成了循环,违反了程序的确定性原则。代码如下图所示: 如这样相互包含的问题,可以使用前置声明来解决。即:在头文件中声明该类,在实现文件中包含该类。如下图所示: 解析 为什么这样使用前置声明,即在AAA.h中声明class BBB; 在BBB.h中声明class AAA; 且成员变量写为所声明类的指针变量, 便不会产生相互包含的错误呢? 原因

bigchen 1909

typedef 的前置声明

1.前置声明在C++大型项目中非常重要,减少编译时相互连接

ranky2009的专栏 6161

C++中前置声明介绍

前置声明是指对类、函数、模板或者结构体进行声明,仅仅是声明,不包含相关具体的定义。在很多场合我们可以用前置声明来代替#include语句。类的前置声明只是告诉编译器这是一个类型,但无法告知类型的大小,成员等具体内容。在未提供完整的类之前,不能定义该类的对象,也不能在内联成员函数中使用该类的对象。而头文件则一一告之。前置声明,也称前向声明(forward declaration)。

weixin_58045467的博客 2502

c语言 前置声明,详解C++ 类的前置声明的使用

刚开始学习C++的人都会遇到这样的问题:定义一个类 class A,这个类里面使用了类B的对象b,然后定义了一个类B,里面也包含了一个类A的对象a,就成了这样://a.h#include "b.h"class A{....private:Bb;};//另一个头文件 b.h#include "a.h"class B{....private:Aa;};一编译,就出现了一个互包含的问题了,这时就有人跳...

weixin_32304579的博客 2932

前置声明 & #include

摘要:前置声明是C++中解决循环依赖和优化编译效率的核心工具,通过仅声明标识符存在而不暴露完整定义来实现。其适用于指针/引用参数、返回值及类指针成员等场景,但值类型参数和成员访问仍需完整定义。与#include相比,前置声明能减少头文件依赖,显著提升大型项目(如Nginx、Redis)的编译速度。工业级项目中,应在头文件中使用前置声明,在实现文件中包含头文件,同时避免过度使用导致依赖混乱。典型案例展示了如何用前置声明解决日志模块和配置模块的循环依赖问题,并通过Linux工具检查合理性。

m0_62807361的博客 798

什么时候可以使用前置声明,使用前置声明有什么限制条件。

首先,我们为什么要包括头文件? 问题的回答很简单,通常是我们需要获得某个类型的定义(definition)。那么接下来的问题就是,在什么情况下我们才需要类型的定义, 在什么情况下我们只需要声明就足够了? 问题的回答是当我们需要知道这个类型的大小或者需要知道它的函数签名的时候,我们就需要获得它的定义。问题分析(一):假设我们有类型A和类型C,在哪些情况下在A需要C的定义: ①A继承至C ②A有一个类型为C的成员变量 ③A有一个类型为C的指针的成员变量 ④A有一个类型为C的引用的成员...

qfturauyls的博客 1516

C++中的前置声明

前置声明是指对类、函数或者模板进行声明,仅仅是声明,不包含相关具体的定义。在很多场合我们可以用前置声明来代替#include语句。而且对于普通的类来说,建议使用前置声明,而不是#include。

《致青春》——云梦泽 2451
上一篇: APSys'2011见闻
下一篇: 软件检测之缺陷模式库
IEEE2007
博客等级 码龄20年 4粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值