C++中前置声明介绍
前置声明是指对类、函数、模板或者结构体进行声明,仅仅是声明,不包含相关具体的定义。在很多场合我们可以用前置声明来代替#include语句。
类的前置声明只是告诉编译器这是一个类型,但无法告知类型的大小,成员等具体内容。在未提供完整的类之前,不能定义该类的对象,也不能在内联成员函数中使用该类的对象。而头文件则一一告之。
如:class Screen;
前置声明,也称前向声明(forward declaration)。在声明之后,定义之前,类Screen是个不完整类型(incomplete type),即已知Screen是一个类型,但是不知道包含哪些成员。
不完全类型只能以有限方式使用。不能定义该类型的对象。不完全类型只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数。
可以通过前置声明配合指针或引用类型声明来减少编译依赖。
Never #include a header when a forward declaration will suffice.
前置声明的作用:
(1)、可以减少编译依赖、减少编译时间(如果头文件被修改,会导致多次重新编译);
(2)、可以隐藏细节;
(3)、可以减少类大小(前置声明会告诉这个类的存在,而不用提供类定义的所有细节);
(4)、减少include,防止类间相互引用形成依赖,造成编译不通过.
以下是在Google C++风格指南中对前置声明的介绍:
尽可能地避免使用前置声明。使用#include 包含需要的头文件即可。
所谓前置声明(forward declaration)是类、函数和模板的纯粹声明,没伴随着其定义.
优点:
(1)、前置声明能够节省编译时间,多余的 #include 会迫使编译器展开更多的文件,处理更多的输入。
(2)、前置声明能够节省不必要的重新编译的时间。 #include 使代码因为头文件中无关的改动而被重新编译多次。
缺点:
(1)、前置声明隐藏了依赖关系,头文件改动时,用户的代码会跳过必要的重新编译过程。
(2)、前置声明可能会被库的后续更改所破坏。前置声明函数或模板有时会妨碍头文件开发者变动其 API.例如扩大形参类型,加个自带默认参数的模板形参等等。
(3)、前置声明来自命名空间std:: 的 symbol 时,其行为未定义。
(4)、很难判断什么时候该用前置声明,什么时候该用 #include 。极端情况下,用前置声明代替 includes 甚至都会暗暗地改变代码的含义.
结论:
(1)、尽量避免前置声明那些定义在其他项目中的实体.
(2)、函数:总是使用#include.
(3)、类模板:优先使用#include.
以下摘自《Using Incomplete(Forward) Declarations》:
An incomplete declaration(an incomplete declaration is often called a forward declaration) is the keyword class or struct followed by the name of a class or structure type.It tells the compiler that the named class or struct type exists, but doesn't say anything at all about the member functions or variables of the class or struct; this omission means that it is a (seriously) incomplete declaration of the type. Since an incomplete declaration doesn't tell the compiler what is in the class or struct, until the compiler gets the complete declaration, it won't be able to compile code that refers to the members of the class or struct, or requires knowing the size of a class or struct object (to know the size requires knowing the types of the member variables).
Use an incomplete declaration in a header file whenever possible. By using an incomplete declaration in a header file, we can eliminate the need to #include the header file for the class or struct, which reduces the coupling, or dependencies,between modules, resulting in faster compilations and easier development. If the .cpp file needs to access the members of the class or struct, it will then #include the header containing the complete declaration.
When will an incomplete declaration work in a header file:
(1)、If the class type X appears only as the type of a parameter or a return type in a function prototype.
class X;
X foo(X x);
(2)、If the class type X is referred to only by pointer (X*) or reference (X&), even as a member variable of a class declared in A.h.
class X;
class A {
/* other members */
private:X* x_ptr;X& x_ref;
};
(3)、If you are using an opaque type X as a member variable of a class declared in A.h.This is a type referred to only through a pointer,and whose complete declaration is not supposed to be available, and is not in any header file. Thus an incomplete declaration of the type is the only declaration your code will ever make or need either in A.h or A.cpp.When will an incomplete declaration not work in a header file:
(1)、If your A.h header file declares a class A in which the incompletely declared type X appears as the type of a member variable.
class X;
class A {
private:X x_member; // error- can't declare a member variable of incomplete type!
};
(2)、If your A.h header file declares a class A in which the incompletely declared type X is abase class (A inherits from X).class X;
class A : public X { // error - baseclass is incomplete type!
(3)、If you don't actually know the name of the type. You can't forward declare a type unless you know its correct name. This can be a problem with some of the types defined in the Standard Library, where the normal name of the type is actually a typedef for a particular template instantiated with some other type, usually with multiple template parameters. For example, the following will not work to incompletely declare the std::string class:class std::string;
在Google C++风格指南中,指出尽可能地避免使用前置声明。而在《Using Incomplete(Forward) Declarations》中,指出能用前置声明代替#include的时候,应尽量用前置声明。以下的内容是摘自:http://stackoverflow.com/questions/553682/when-can-i-use-a-forward-declaration
#ifndef FBC_MESSY_TEST_FORWARD_DECLARATION_HPP_
#define FBC_MESSY_TEST_FORWARD_DECLARATION_HPP_// reference: http://stackoverflow.com/questions/553682/when-can-i-use-a-forward-declaration/*Put yourself in the compiler's position: when you forward declare a type,all the compiler knows is that this type exists; it knows nothing aboutits size, members, or methods. This is why it's called an incomplete type.Therefore, you cannot use the type to declare a member, or a base class,since the compiler would need to know the layout of the type.
*/
// Assuming the following forward declaration.
class X;// Here's what you can and cannot do.// 1. What you can do with an incomplete type:
// 1.1 Declare a member to be a pointer or a reference to the incomplete type:
class Foo_1 {X *pt1;X &pt2;
};// 1.2 Declare functions or methods which accept/return incomplete types:
void f1(X);
X f2();/* 1.3 Define functions or methods which accept/return pointers/references tothe incomplete type (but without using its members): */
void f3(X*, X&) {}
X& f4() { X* x = nullptr; return *x; }
X* f5() { X* x = nullptr; return x; }// 2. What you cannot do with an incomplete type:
// 2.1 Use it as a base class
// class Foo_2 : X {} // compiler error!// 2.2 Use it to declare a member:
/* class Foo_2 {X m; // compiler error!
}; */// 2.3 Define functions or methods using this type
// void f6(X x) {} // compiler error!
// X f7() {} // compiler error!/* 2.4 Use its methods or fields,in fact trying to dereference a variable with incomplete type */
/* class Foo_3 {X *m;void method() {m->someMethod(); // compiler error!int i = m->someField; // compiler error!}
}; *//*When it comes to templates, there is no absolute rule:whether you can use an incomplete type as a template parameter isdependent on the way the type is used in the template.
*//*"In computer programming, a forward declaration is a declaration of an identifier(denoting an entity such as a type, a variable, or a function) for which theprogrammer has not yet given a complete definition."In C++, you should forward declare classes instead of including headers.Don’t use an #include when a forward declaration would suffice.When you include a header file you introduce a dependencythat will cause your code to be recompiled whenever the header file changes.If your header file includes other header files, any change to those files willcause any code that includes your header to be recompiled.Therefore, you should prefer to minimize includes,particularly includes of header files in other header files.You can significantly reduce the number of header filesyou need to include in your own header files by using forward declarations.
*/#endif // FBC_MESSY_TEST_FORWARD_DECLARATION_HPP_
GitHub: https://github.com/fengbingchun/Messy_Test
相关文章:

在Java SE中使用Hibernate处理数据
如今,Hibernate正在迅速成为非常流行的(如果不是最流行的)J2EE O/R映射程序/数据集成框架。它为开发人员提供了处理企业中的关系数据库的整洁、简明且强大的工具。但如果外部需要访问这些已被包装在J2EE Web应用程序中的实体又该怎么办&#…

利用OpenCV、Python和Ubidots构建行人计数器程序(附完整代码)
作者 | Jose Garcia译者 | 吴振东校对 | 张一豪、林亦霖,编辑 | 于腾凯来源 | 数据派(ID:datapi)导读:本文将利用OpenCV,Python和Ubidots来编写一个行人计数器程序,并对代码进行了较为详细的讲解…
开源软件License汇总
开源软件英文为Open Source Software,简称OSS,又称开放源代码软件,是一种源代码可以任意获取的计算机软件,这种软件的著作权持有人在软件协议的规定之下保留一部分权利并允许用户学习、修改以及以任何目的向任何人分发该软件。 某…

前深度学习时代CTR预估模型的演化之路:从LR到FFM\n
本文是王喆在 AI 前线 开设的原创技术专栏“深度学习 CTR 预估模型实践”的第二篇文章(以下“深度学习 CTR 预估模型实践”简称“深度 CTR 模型”)。专栏第一篇文章回顾:《深度学习CTR预估模型凭什么成为互联网增长的关键?》。重看…

神器与经典--sp_helpIndex
每每和那些NB的人学习技术的时候,往往都佩服他们对各个知识点都熟捻于心,更佩服的是可以在很短时间找出很多业界大师写的文章和开发的工具,就像机器猫的口袋,让人羡慕嫉妒恨啊!宋沄剑宋桑就是其中之一,打劫其硬盘的念头已计划很久,只待时机成…

评分9.7!这本Python书彻底玩大了?程序员:真香!
「超级星推官/每周分享」是一个围绕程序员生活、学习相关的推荐栏目。CSDN出品,每周发布,暂定5期。关键词:靠谱!优质!本期内容,我们将抽1人送出由我司程序员奉为“超级神作”的《疯狂Python讲义》1本&#…

Caffe源码中caffe.proto文件分析
Caffe源码(caffe version:09868ac , date: 2015.08.15)中有一些重要文件,这里介绍下caffe.proto文件。在src/caffe/proto目录下有一个caffe.proto文件。proto目录下除了caffe.proto文件外,还有caffe.pb.h和caffe.pb.cc两个文件,此两个文件是根…

这套完美的Java环境安装教程,完整,详细,清晰可观,让你一目了然,简单易懂。⊙﹏⊙...
JDK下载与安装教程 2017年06月18日 22:53:16 Danishlyy1995 阅读数:349980版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012934325/article/details/73441617学习JAVA,必须得安装一下JDK(java dev…

【畅谈百度轻应用】云时代·轻应用·大舞台
云时代轻应用大舞台刘志勇君不见,上下班的地铁上,低头看手机;同事吃饭聊天,低头看手机;甚至朋友聚会,忙里偷闲打个招呼,然后继续低头看手机。正如微博上一个流传甚广的段子:“世界上…

如何画出高级酷炫的神经网络图?优秀程序员都用了这几个工具
(图片付费下载于视觉中国)作者 | 言有三 来源 | 有三AI(ID:yanyousan_ai)【导读】本文我们聊聊如何才能画出炫酷高大上的神经网络图,下面是常用的几种工具。1、NN-SVGNN-SVG 可以非常方便的画出各种类型的…
OpenBLAS简介及在Windows7 VS2013上源码的编译过程
OpenBLAS(Open Basic Linear Algebra Subprograms)是开源的基本线性代数子程序库,是一个优化的高性能多核BLAS库,主要包括矩阵与矩阵、矩阵与向量、向量与向量等操作。它的License是BSD-3-Clause,可以商用,目前最新的发布版本是0.…

技本功丨请带上纸笔刷着看:解读MySQL执行计划的type列和extra列
本萌最近被一则新闻深受鼓舞,西工大硬核“女学神”白雨桐,获6所世界顶级大学博士录取通知书。货真价值的才貌双全,别人家的孩子高考失利与心仪的专业失之交臂,选择了软件工程这门自己完全不懂的专业.即便全部归零,也要…

精美素材分享:16套免费的扁平化图标下载
在这篇文章中你可以看到16套华丽的扁平化图标素材,对于设计师来说非常有价值,能够帮助他们节省大量的时间。这些精美的扁平化图标可用于多种用途,如:GUI 设计,印刷材料,WordPress 主题,演示&…
Caffe源码中math_functions文件分析
Caffe源码(caffe version:09868ac , date: 2015.08.15)中有一些重要文件,这里介绍下math_functions文件。1. include文件:(1)、<glog/logging.h>:GLog库,它是google的一个开源的日志库,其使用可以参考&…

论文推荐 | 目标检测中不平衡问题算法综述
(图片付费下载于视觉中国)作者 | CV君来源 | 我爱计算机视觉(ID:aicvml)今天跟大家推荐一篇前几天新出的投向TPAMI的论文:Imbalance Problems in Object Detection: A Review,作者详细考察了目标…

php使用redis的GEO地理信息类型
redis3.2中增中了对GEO类型的支持,该类型存储经纬度,提供了经纬设置,查询,范围查询,距离查询,经纬度hash等操作。 <?php$redis new Redis(); $redis->connect(127.0.0.1, 6379, 60); $redis->au…
Caffe源码中syncedmem文件分析
Caffe源码(caffe version:09868ac , date: 2015.08.15)中有一些重要文件,这里介绍下syncedmem文件。1. include文件:(1)、<caffe/common.hpp>:此文件的介绍可以参考:http://blog.csdn.net/fengbingchun/article/detail…

免费开源!新学期必收藏的AI学习资源,从课件、工具到源码都齐了
(图片付费下载于视觉中国)整理 | Jane出品 | AI科技大本营(ID:rgznai100)2019 年 3 月 28 日,教育部公布了 2018 年度普通高等学校本科专业备案和审批结果,共有 35 所大学新增了独立的人工智能专…

win7利用remote连接服务器,显示发生身份验证错误 要求的函数不受支持
先参考1: https://blog.csdn.net/qq_35880699/article/details/81240010 发现我根本没找到oracle修正的那个文件! 然后我搜索:win7没有oracle修正文件,-------按照参考2中的链接操作,我发现我根本没有CredSSP文件&…

java参数传递:值传递还是引用传递
2019独角兽企业重金招聘Python工程师标准>>> 基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的; 在Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数…

干货 | 收藏!16段代码入门Python循环语句
(图片付费下载于视觉中国)作者 | 李明江 张良均 周东平 张尚佳,本文摘编自《Python3智能数据分析快速入门》来源 | 大数据(ID:hzdashuju)【导读】本文将重点讲述for语句和while语句。for语句属于遍历循环&a…

Intel TBB简介及在Windows7 VS2013上源码的编译过程
Intel TBB(Intel Threading Building Blocks)是Intel线程构建块开源库,它的License是Apache 2.0.Intel TBB是一种用于并行编程的基于C语言的框架,它是一套C模板库。它提供了大量特性,具有比线程更高程度的抽象。Intel TBB可以在Windows、Linu…

react中ref的使用
在react中获取真实dom的时候就需要用到ref属性,具体使用如下 var MyComponent React.createClass({handleClick: function() {console.log(this.input)},render: function() {return (<div><input type"text" ref{(input) > {this.input in…
Caffe源码中blob文件分析
Caffe源码(caffe version commit: 09868ac , date: 2015.08.15)中有一些重要的头文件,这里介绍下include/caffe/blob.hpp文件的内容:1. Include文件:(1)、<caffe/common.hpp>:此文件的介绍可以参考:http://…

jQuery之替换节点
如果要替换节点,jQuery提供了两个方法:replaceWith()和replaceAll()。 两个方法的作用相同,只是操作颠倒了。 作用:将所有匹配的元素都替换成指定的HTML或者DOM元素。(摘自《锋利的jQuery(第二版)》P72) 基…

比特大陆发布第三代AI芯片,INT8算力达17.6Tops
9月17日,福州城市大脑暨闽东北信息化战略合作发布会在数字中国会展中心隆重召开。本次发布会上,比特大陆正式推出了第三代AI芯片BM1684,同时也宣布BM1684将作为底层算力,赋能福州城市大脑,助力数字福州、数字中国的建设…

在 Azure 网站上使用 Memcached 改进 WordPress
编辑人员注释:本文章由 Windows Azure 网站团队的项目经理 Sunitha Muthukrishna 和 Windows Azure 网站开发人员体验合作伙伴共同撰写。 您是否希望改善在 Azure 网站服务上运行的 WordPress 网站的性能?如果是,那么您就需要一个可帮助加快您…
Caffe源码中io文件分析
Caffe源码(caffe version commit: 09868ac , date: 2015.08.15)中有一些重要的头文件,这里介绍下include/caffe/util/io.hpp文件的内容:1. include文件:(1)、<google/protobuf/message.h>:关于protobuf的介绍可以参考&…

DeepMind悄咪咪开源三大新框架,深度强化学习落地希望再现
作者 | Jesus Rodriguez译者 | 夕颜出品 | AI科技大本营(ID:rgznai100)【导读】近几年,深度强化学习(DRL)一直是人工智能取得最大突破的核心。尽管取得了很多进展,但由于缺乏工具和库,DRL 方法仍…

seq2seq
链接: https://blog.csdn.net/wuzqchom/article/details/75792501 转载于:https://www.cnblogs.com/yttas/p/10631442.html