变量/常量,例如extern int var1;;
函数,例如void foo();,把稳类的成员函数无法单独做前置声明;
类,例如class Foo;,也可以前置声明模板类:template class<typename T1, int SIZE>Foo;。如果类包含在名字空间中,需在名字空间内做前置声明:namespace tlanyan {class Foo;};,而不能这样:class tlanyan::Foo;。

前置声明浸染
根据其用场,前置声明的紧张浸染为:
(1)避免重复定义变量;
(2)避免引入函数定义/声明文件,从而函数文件发生变动时不会重新编译依赖文件;
(3)办理循环依赖问题。
前两种用场好理解,第三种轻微繁芜点,但却是前置声明最主要的用场。其办理类A包含类B,同时类B包含类A的依赖问题。循环依赖一样平常是设计层面的问题,可通过接口、引入赞助类等手段化解。前置声明也能办理,只是架构上轻微别扭。
不管A和B是否定义在同一个文件中,c++永久无法办理如下形式的循环依赖(后文阐明缘故原由):
前置声明办理该问题须要与指针合营,转换成另一种形式。要点如下:
至少将某类的变量类型转换成指针,例如A中将B转成B;
类A中对B利用前置声明;
类A的定义文件中移除对类B文件的包含(做了包含保护则可忽略)。
利用前置声明后,以下是一种可行的办理形式(两个类均利用了前置声明):
深入前置声明
如果你有其他编程措辞的履历,会创造c++有点怪异:Java/C#/Python/PHP等措辞可以轻松做到循环引用,无需利用类似的前置声明技巧。这不禁让人思考:C++为何必必要用前置声明才能化解?
缘故原由在于C++定义工具有两种办法:一种是A a形式,a即工具,调用成员变量或函数用.,工具在栈等分配;另一种是A a,a是指针,调用成员变量或函数用->,其指向地址存储实际工具,工具在堆等分配。
分配工具须要知道详细的内存大小,但以下形式我们不能确定类A和类B工具的大小:
对付这个大略例子,你可以直不雅观认为A和B占用同样的内存,例如1字节,但也可以是2字节,3字节等;根据内存对齐哀求,一样平常是4字节,8字节等。无论哪种情形,编译器无法确定其工具占用内存,便会报错停滞编译。以是你该当知道为什么C++永久不应该(不能)这样做了吧?
那为何前置声明加指针的组合能办理循环引用问题的呢?由于正常情形下,数据类型指针在同一机器的编译器里占同样的内存。指针一样平常是4或者8个字节,对应32和64位指针。用了指针,纵然有循环引用,类的大小也能轻易的确定下来。这也是Java/C#/Python/PHP等可以轻松循环引用的缘故原由:这些措辞中,工具变量实在都是指针,也意味着工具变量都是引用通报。
如果不移除文件的相互包含,能否省去前置声明呢?答案是不能,缘故原由如下:
1、C++按照一个个编译单元(translation unit)进行编译,如果两个文件相互包含且没有#pragma once等包含保护方法,则会涌现递归包含,编译器报错;
2、如果两个头文件都有文件包含保护,编译A时会把B包含进来,但由于B包含了A,A中的包含保护生效,导致B文件内的内容实际未引入A,于是报B为未知符号的缺点。
总的来说,不管是否移除对方的头文件,前置声明都是必须的。实践中为了避免文件变动时重新编译的耗费,移除不必要的头文件是一个好习气。
那么本日的分享就到这里了,后续会更新更多精彩项目或者知识内容的,大家要好好学C措辞C++哟~
写在末了:对付准备学习C/C++编程的小伙伴,如果你想更好的提升你的编程核心能力(内功)不妨从现在开始!
编程学习书天职享:
编程学习视频分享:
整理分享(多年学习的源码、项目实战视频、项目条记,根本入门教程)
欢迎转行和学习编程的伙伴,利用更多的资料学习发展比自己琢磨更快哦!
对付C/C++感兴趣可以关注小编在后台私信我:【编程互换】一起来学习哦!
可以领取一些C/C++的项目学习视频资料哦!
已经设置好了关键词自动回答,自动领取就好了!