C++中头文件包含问题

c++类相互引用的问题,如何避免头文件相互包含 如果是在类B成员变量中使用A,那就在B的头文件中,前向声明一个类A,并且在B中定义一个指向A的指针pA,不需要有A的实例的创建,这时候就不需要知道A的定义了,就可以避免包含A的头文件。而在类B的cpp文件中去包含A的头文件,在cpp文件中创建pA的实例。如果只在B的成员函数中使用类A,那就更简单了,只需要在类B的cpp文件中包含类A的头文件就可以了。两个类A,B,相互引用,如果互相包含彼此的头文件,造成无限包含,编译出错。如果只有类A的声明而没有包含实际的头文件,就会导致类的不完整定义错误。 阅读详情

 C++中基础类互相引用带来的问题

在一些大的工程中,可能会包含几十个基础类,免不了之间会互相引用 ( 不满足继承关系,而是组合关系 ) 。也就是需要互相声明。好了,这时候会带来一些混乱。如果处理得不好,会搞得一团糟,根据我的经验,简单谈谈自已的处理办法:

编码时,我们一般会尽量避免 include 头文件,而是采用声明 class XXX 。 但有时候还是必须用 Include 头文件,那么,两者的划分在于什么呢?

应该是很明确的,但书上好像都少有提及。

首先:
我们要明白为什么要用声明取代头文件包含:对了,是为了避免无必要的重编译 ( 在头文件发生变更时 ) 。 工程较大,低速机,或基础类经常变更 ( 不合理的设计吧 ) ,编译速度还是会在意的, 另外,更为重要的是,采用声明可降低代码 (class) 之间的藕合度,这也是面向对象设计的一大原则。

二:一般原则:
a.
头文件中尽量少 include, 如果可以简单申明 class clsOld; 解决,那最好。减少没有必要的 include;
b.
实现文件中也要尽量少 include, 不要 include 没有用到的头文件。

三:那什么时候可以只是简单声明 class clsOld 呢?
简单的说:不需要知道 clsOld 的内存布局的用法都可以 ( 静态成员除外 ) ,也就是讲如果是指针或引用方式的 都行。
比如:
   clsOld * m_pOld;    //
指针占 4 个字节长
   clsOld & test(clsOld * pOld) {return *pOld};
 
一切 OK 。

四:什么时候不能简单声明 class clsOld ,必须 include 呢?
不满足三的情况下:
 
比如:
         clsOld m_Objold;  //
不知道占据大小,必须要通过它的具体声明来计算
原因很简单,想想你要计算 sizeof(classNew) ,但连 clsOld 的 size 都不知道,编译器显然会无能为力。

特殊情况:
          int test() { return clsOld::m_sInt;}
    
静态成员调用,想来应该是不需要知道内存布局的,但因为需要知道 m_sInt 是属于 clsOld 命名空间 的,如果只声明 class xxx 显然是不足以说明的,所以必须包含头文件。

综上所述,我有以下几点建议:
1
:如果有共同相关依赖 ( 必须 include) 的类,比如 A,B 都依赖 D 可以放在一起,然后直接 Include "d" 类的使用者只需关心与本类暴露出的相关类型,内部用到的类型不用去管 ( 不用自已去 include d) 。这样 给出的 class ,调用者才更好用 ( 不用去看代码查找,是不是还需要包含其它头文件 ) 。

2 :如果 A 类依赖 D B 类不依赖 D ,可以把它们分开两个头文件。各自 Include 。这样可避免当 D 发生变化时, 避免不必要重编译。

3 :类中尽量采用指针或引用方式调用其它类,这样就可以只声明 class xxx 了。并且这也符合资源最优 利用,更利于使用多态。

/--------------------------------------------------/////////////////////////////////////////////////////////////////////////////

   今天用VC++编译我这昨天写的代码时发现总是通不过,看到大部分的错误都是与一个类的定义有关。

  明明我已经在这个类中定义了一个成员变量,可编译器偏要说那个变量不是这个类的成员。没办法,找了半天原因还是没有头绪。再三地确认不是我C++的语法错误之后。我开始怀疑是不是头文件的问题。因为当我把一些#include "..."搬到#pragma once之前或者之后,错误报告就会发生变化。有时就只是说我的一个类重复定义了。

以前用C写头文件的时候都是用宏定义来避免重复包含头文件。C++里虽然也还可用这个方法,但VC++就是不用,它用的是#pragma once。这一变化对我来说真是有点摸不着头脑了,我不清楚#pragma once的工作方式是如何的。而我现在遇到的问题又与这个有关。找找网上的内容看吧。上google搜了半天,那些论坛里的回答基本上都是“防止重复包含头文件的,你不用管他。”这样的。可是不管他真的行吗?我刚学的VC++,我看的书上是没有讲过这个内容的。怎么在网上也搜不到呢?经过我不懈的努力,终于让我找到了一篇http://www.yesky.com/127/1736627_3.shtml。

作者Adding的这段话对我的帮助最大:“ 既然使用了包含文件,为什么还要在class CMainFrame前添加"class CViewerView;"等代码?如果用包含文件代替它,行不行?  很多Visual C++书籍对这些问题避而不谈,但实际上这是一个重要的问题。如果不能理解上述代码,我们很可能为无法通过编译而大伤脑筋。这些问题的出现是基于这样的一些事实:在我们用标准C/C++设计程序时,有一个原则即两个代码文件不能相互包含,而且多次包含还会造成重复定义的错误。为了解决这个难题, Visual C++使用#pragma once来通知编译器在生成时只包含(打开)一次,也就是说,在第一次#include之后,编译器重新生成时不会再对这些包含文件进行包含(打开)和读取,因此我们看到在用向导创建的所有类的头文件中有#pragma once语句就不会觉得奇怪了。然而正是由于这个语句而造成了在第二次#include后编译器无法正确识别所引用的类。因此,我们在相互包含时还需要加入类似class CViewerView这样的语句来通知编译器这个类是一个实际的调用。 ”

看来就是这个问题了。把我的代码一加上那些类的声明以后果然通过了编译。我感觉这个问题在VC++里面来说应该是值得注意的。可能是由于我刚学VC++,见识太少的原故吧。无论如何先记下来,说不定也有人在为这个#pragma once伤脑筋呢。

 

头文件包含其实是一想很烦琐的工作,不但我们看着累,编译器编译的时候也很累,再加上头文件中常常出现的宏定义。感觉各种宏定义的展开是非常耗时间的,远不如自定义函数来得速度。我仅就不同头文件、源文件间的句则结构问题提出两点原则,仅供参考:

第一个原则应该是,如果可以不包含头文件,那就不要包含了。这时候前置声明可以解决问题。如果使用的仅仅是一个类的指针,没有使用这个类的具体对象(非指针),也没有访问到类的具体成员,那么前置声明就可以了。因为指针这一数据类型的大小是特定的,编译器可以获知。

第二个原则应该是,尽量在CPP文件中包含头文件,而非在头文件中。假设类A的一个成员是是一个指向类B的指针,在类A的头文件中使用了类B的前置声明并便宜成功,那么在A的实现中我们需要访问B的具体成员,因此需要包含头文件,那么我们应该在类A的实现部分(CPP文件)包含类B的头文件而非声明部分(H文件)。

华为技术有限公司c语言编程规范 立即下载

相关推荐

C++头文件包含问题的详细总结

不同头文件中的类的嵌套在实际编程中,不同的类一般是放在不同的相互独立的头文件中的,这样两个类在相互引用时又会有不一样的问题。重复编译是问题出现的根本原因。为了保证头文 件仅被编译一次,在C++中常用的办法是使用条件编译命令。。。

c++包含自定义头文件

在c++中自定义的库通过源码复用的方式在其他项目中使用,需要添加相应的头文件,有以下几种方式在其他项目中包含自定义的头文件: 将自定义库的头文件(.h)与源文件(.cpp)复制到当前项目文件夹下,然后在项目距中使用#include "headerfile.h"即可(缺点是每个新项目都要去赋值头文件与源文件,而且如果自定义库发生了变化还要重新复制新文件到其依赖项目下) 在菜单栏选择项目-项目属性-...

liyunxin_c_language的博客 6024

Cadence Allegro 17.4学习记录开始01-原理图Capture CIS 17.4

Orcad的学习记录

qq_31444421的博客 1万+

关于C++明明包含了头文件确报错

1.头文件里用class A ....来试着解决。2.源文件里包含那个所需要的头文件。

m0_73165531的博客 2131

MODTRAN5.2.1安装配置

MODTRAN5.2.1安装配置

Home 4255

Zynq 双核AMP 通信

4、配置离线编译(这里不讲),配置linux的内核地址空间(0x4000_0000改为0x2000_0000),以及单核启动。CPU1设置为0x2000_0000~0x3FFF_FFFF(也可以小于0x3FFF_FFFF)如果禁用CPU1的L2 cache,在CPU1的bsp里面添加编译时候所需要的宏。3、配置工程,将vivado产生的.xsa文件复制到amp_com项目目录下。9、使用petalinux-package --boot 打包。一、vivado工程。5、编译u-boot。

y183128184的博客 1086

c++头文件添加了提示找不到文件

相信大家也遇到新建了一个项目,使用到一些第三方或者自己写的库或者文件之类的 在引用中明明添加了对文件或者库的路径引用,但编译的时候还是提示找不到文件。 给大家提供一个思路L: 1.查找需要引用文件在本项目中的绝对和相对路径,一般用到相对路径较多 2.查看引用该类的实际文件中对该类的引用地址的完整度 3.如果有添加整体一个搜索路径,那就需要结合整体搜索的路径和文件中对该类的引用地址,如过和查找到的文件在项目中的相对路径一致,重新编译项目就可以了 这里以codeblocks这个IDE工具..

jiletianzun的博客 5635

python监听海康威视报警服务器

因为我使用海康威视摄像头是自带热成像的所以事件报警会上报两张图片,一张是RGB图像、另一张是热成像图像,因此使用。拿到的就是第一张RGB图像。可以点击测试,会显示。

qq_57018478的博客 1157

C++文件包含常见问题

这类错误通常是由于重复包含了某种变量或类的声明,但是很多时候,我们需要在多个类中引用同样的变量,所以当然希望把这些数据写到一个文件中,然后在不同的类中include它。而这会直接导致“重定义错误”,解决办法如下: 以下是转载内容:C++中的全局变量 在C++中定义全局变量是应该尽量在.cpp文件中定义,而不要在.h 文件中 定义,定义好了之后,可以在.h文件中利用 extern关键字进

loveqinj的专栏 755

Versal ACAP NoC实战:像理解计算机网络一样配置AXI NoC,打通PS与PL数据通路

本文深入探讨了Versal ACAP NoC的配置与优化,通过计算机网络类比解析NoC架构,详细介绍了在VD100开发板上配置AXI NoC实现PS与PL数据交互的实战步骤。文章涵盖NoC组件功能、Vivado配置技巧、性能优化方法及常见问题解决方案,帮助开发者高效打通Versal芯片的数据通路。

weixin_42665255的博客 291

在claude code中使用glm模型出现Unable to connect to Anthropic services的解决方案

本文主要介绍了在claude code中使用glm模型出现Unable to connect to Anthropic services的解决方案,希望能对使用claude code的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 13万+

c++ 头文件互相包含问题

c++ error C2039 C2061 C3646 C4430 C2504 未知重写说明符 缺少类型说明符-假定为int 不是xxx的成员

weixin_44197671的博客 982

【HYSPLIT 教程第二期】Inline WRF-HYSPLIT 耦合

【HYSPLIT 教程第二期】Inline WRF-HYSPLIT 耦合

WW、forever的博客 808

C++头文件包含(2):cpp多次包含同一头文件,会有什么问题?头文件保护

1、目录结构: /base /main main.cpp CMakeLists.txt /test1 test.h 2、文件内容: 2.1、不加头文件保护:多次包含重定义问题 // main.cpp #include "test.h" #include "test.h" int main() { func(); return 0; } // CMakeLists.txt i

个人工作中学到的专业技术与职业发展知识笔记 2184

基于YOLOv8与UI界面的短视频内容审核系统实现与深度学习应用

YOLO(You Only Look Once)是一种用于实时物体检测的深度学习模型,它能在单次前向传播中同时完成物体检测和定位。YOLOv8是YOLO系列中的最新版本,相较于之前的版本,YOLOv8具有更高的检测精度和更快的推理速度,特别适合需要实时检测的应用场景。YOLOv8通过卷积神经网络(CNN)来提取图像中的特征,并通过多个卷积层来预测每个目标的位置和类别。该模型的优势在于其端到端的结构,使得在视频监控、自动驾驶、安防监控等实时应用中,能够实现快速且高效的目标检测。

YOLO 314

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

C++:头文件递归包含问题(互相包含问题)

目录引言初始版本头文件守卫递归包含会怎么样为什么会出错前置声明是什么如何解决递归包含问题参考 引言 最近正在疯狂补技术债,以及疯狂赶项目…大一大二摸的鱼终归是要还的,也奉劝大家少摸鱼,不然临近找工作可能就会像我一样焦虑。 在写C++项目中,碰到一个非常古怪的问题,当我像往常一样引入一个头文件时,vscode居然给我报红了(我在vscode中使用的是clangd插件): 当时就觉得非常震惊,我从未没碰到过只是include一个头文件,居然会报错的情况,当我以为是插件的问题,像往常一样mkdir build &

NiGo的博客 8848

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C++头文件包含的问题

问题: 一个文件不要包含两个相同的头文件 解决方式: //在预编译阶段将忽略重复包含的该头文件,判断重复的依据是文件名是否相同 #pragma once //如果定义了宏变量TEST_H_则忽略宏内命令,即虽然该重复的头文件被包含进去了,但是其中的关键内容却被忽略了,所以不会发生冲突 #ifndef TEST_H_ #define TEST_H_ //头文件内容 #endif 头文件之间不要相互包含 补充: 两个cpp文件可以包含同一个头文件,这不会算作重复包含(它们在连接的时候才会相遇,

Romain的博客 767

android 蓝牙通讯demo

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

C++中头文件互相包含问题

信心满满地做了一个程序,十分顺手,半个小时搞定,F5编译,竟然报错 “1>d:\vc2005\meetingroom\meetingroom\RoomManager.h(20) : error C2143: 语法错误 : 缺少“;”(在“*”的前面) 1>d:\vc2005\meetingroom\meetingroom\RoomManager.h(20) : error C4430: 缺少类

smells2的专栏 2460

C/C++ 中头文件相互包含引发的问题

C/C++ 中头文件相互包含引发的问题 今天下午遇到一个头文件相互包含而导致的编译问题,花了我不少时间去调试没找到问题,最后晚上跟师兄讨论不少时间,突然有所顿悟! 问题重现 我把问题脱离于项目简单描述一下:我写了一个函数 bool func(ClassA* CA) 需要加到项目中,我就把这个函数的声明放到 head1.h 中,函数参数类型 ClassA 定义在另一个头文件 hea

海风林影 6万+

解决C++中两个类的头文件互相包含问题

c++常见问题

weixin_44216359的博客 4546

C++头文件相互包含问题解决方法

在某些应用场合,会发生两个头文件之间相互包含,导致头文件间无限死循环包含,编译无法通过。 解决方法其实很简单,在其中一方的源码文件包括头文件即可。但这个“其中一方”有点讲究,最好在设计原则上属于特殊的一方。 下面是例子: //Proc1.h class Proc1{ public: Proc1(); ~Proc1(); void func(); }; //Proc1.cpp include "Proc1.h" include "ProcMgr.h" /

HDZGQ的博客 2791

C/C++ 头文件多层包含问题

今天写代码时遇到个头文件多层包含的问题,竟然想了很久…,下面就分析下,顺便解释下深层次原因。 一 问题 平时写功能代码时,一般一个类单独拥有一个cpp文件和头文件,如下, // func.h #ifndef __FUNC_H__ #define __FUNC_H__ #include "other.h" struct func { void fn1(int data); void fn2...

爱就是是恒久忍耐的专栏 2334

深入理解和探讨C++头文件包含问题

1.头文件包含 1.1 系统头文件与自定义头文件 使用预处理指令 #include 可以引用用户和系统头文件。它的形式有以下两种: #include <stdio.h> 这种形式用于引用系统头文件,编译器自带的头文件就是系统头文件,编译器编译时直接去系统目录找此头文件。 #include "header.h" 这种形式用于引用用户自定义头文件,它优先在包含当前文...

Allen Roson 1654

【c++】头文件互相包含问题

头文件相互包含

jokerMingge的博客 697
上一篇: 回溯法——求子集
下一篇: 回溯——n皇后问题
clearriver
博客等级 码龄19年 104粉丝 94原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值