【M12】了解“抛出一个exception”与“传递一个参数”或“调用一个虚函数”之间的差异
1、方法参数的声明语法和catch语句的语法是一样的,你可能会认为主调方法调用一个方法,并向其传递参数,与抛出一个异常传递到catch语句是一样的,是的,有相同之处,但也有更大的不同。
2、主调方法调用一个方法,控制权转移,被调方法执行完,控制权最终还会返回到主调方法。但是,抛出异常到达catch语句,控制权不会再回到抛出端。
3、那么问题来了,抛出异常到达catch语句,控制权不再会到抛出端,这意味着,抛出的异常离开了作用域,自动销毁,那么catch语句还怎么捕获异常对象呢?
解决办法是:建立一个临时对象,对抛出的异常进行copy构造。特别注意的是,不管什么情况,这个临时对象是必不可少的。根本原因就是,抛出端的异常对象销毁了,必须建立一个临时对象,才能传递到catch语句。而对于调用方法,如果是传递引用,不需要复制对象,因为主调方法中的局部对象并没有销毁。
4、即使抛出的异常没有销毁,抛出的异常对象到catch语句,中间也有一个临时对象。
5、这意味着,catch语句没有办法修改抛出端的异常对象,修改的只是副本,也就是临时对象。
6、从抛出异常到catch语句,之间建立一个临时对象,这个临时对象的类型,是抛出异常对象的表面类型。这就意味着,如果抛出的异常对象,表面类型与真实类型不一致,会造成对象切割。
7、这就导致下面的问题:抛出一个子类,在catch(Base& b)的语句中匹配成功,此时,b的表面类型和真实类型不一致,如果从新抛出b,建立的临时对象就是父类对象,也就是对象切割。也就是说,重新抛出的异常更加抽象,这显然不合理,那怎么办呢?直接使用throw,重新抛出当前的异常对象。并且不再产生一个新的临时对象。
8、catch语句中可以是传值,传引用,传const引用。对于传值,从临时对象到catch语句中形参,还要进行一次copy构造。因此,应该使用传引用,避免这一次的copy构造。那么,对于传const引用呢?
9、我们知道对于内置类型的临时对象,是不能修改的,但是,对于exception是个例外。思考一下,为什么对于内置类型的临时对象不能修改?
临时对象的来源:隐式类型转化,方法返回值,抛出异常。
对于隐式类型转化,临时对象不可修改。如果可修改,赋值给non-const引用,程序员修改这个引用,企图修改原数据,但实际上,修改的是临时对象,这与程序员的期望不符合,造成错觉。因此,禁止这种行为。
对于方法返回值,产生的临时对象不可修改。这是为了,禁止客户对方法返回值进行赋值。
但是,对于抛出异常产生的临时对象,可以修改。为什么?因为有这种需求:对抛出的异常追加一些额外信息。
10、现在考虑指针,抛出一个异常对象,catch语句的参数是指针,不能匹配成功,因为类型不吻合。不能把一个对象赋值给指针,必须取地址,赋值给指针。
11、继续思考,抛出一个指针,catch指针,相当于传递指针。这种情况,要保证指针指向的对象没有销毁。
12、调用方法,参数可以进行隐式类型转换。比如int转化为double。但是,对于抛出异常,不能进行这类的隐式转换。抛出异常可以进行的转换只有两种:子类转化为父类;有型指针转换为无型指针。
13、调用方法是最优匹配,而捕获异常是最先匹配。这就意味着,catch语句捕获的异常应该是,由具体到抽象,否则造成死代码。
【M12】了解“抛出一个exception”与“传递一个参数”或“调用一个虚函数”之间的差异的更多相关文章
- dubbo rpc调用抛出的Exception处理
关于dubbo的Exception堆栈被吃处理,网上已经有比较多的解决方法,在我们的应用场景中,不希望RPC调用对方抛出业务exception,而是通过Resp中的errorCode,errorMsg ...
- 参数在一个线程中各个函数之间互相传递的问题(ThreadLocal)
ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源. 一个ThreadLocal变量虽然是 ...
- VS2013 抛出 stackoverflow exception 的追踪
本公司使用VWG.Caslte ActiveRecord.CSLA.net .Quantz.net 等组件做为公司的开发基础,自2007年以来,一直工作正常,但最近(2015.12月)以来,打开MDA ...
- 从constructor中抛出exception后,constructor会返回null吗?
刚才琢磨这个问题主要是在想,如果constructor抛出了exception,那么返回的object是什么一个情况呢?如果我这个object中有一些关键的资源没有初始化,比如说Database co ...
- (转)spring异常抛出触发事务回滚策略
背景:在面试时候问到事务方法在调用过程中出现异常,是否会传递的问题,平时接触的比较少,有些懵逼. spring异常抛出触发事务回滚策略 Spring.EJB的声明式事务默认情况下都是在抛出unchec ...
- Effective Java 第三版——74. 文档化每个方法抛出的所有异常
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- WCF服务创建与抛出强类型SOAP Fault
原创地址:http://www.cnblogs.com/jfzhu/p/4060666.html 转载请注明出处 前面的文章<WCF服务的异常消息>中介绍过,如果WCF Service发生 ...
- Spring异常抛出触发事务回滚
Spring.EJB的声明式事务默认情况下都是在抛出unchecked exception后才会触发事务的回滚 /** * 如果在spring事务配置中不为切入点(如这里的切入点可以定义成test*) ...
- java 检查抛出的异常是否是要捕获的检查性异常或运行时异常或错误
/** * Return whether the given throwable is a checked exception: * that is, neither a RuntimeExcepti ...
随机推荐
- windows ping RPi 2B
/************************************************************************* * windows ping RPi 2B * 声 ...
- 【jQuery】
TryjQuery:jQuery官方推出的教学视频http://blog.jobbole.com/37699/ jQuery 1.11 / 2.1 beta 版发布,全面支持异步模块加载 √http ...
- Serv-U软件在64位操作系统下使用不了odbc解决方法
这是因为64位Windows上有两个ODBC连接,你需要创建一个32位的ODBC连接.打开32位ODBC管理器的位置 X:\Windows\syswow64\odbcad32.exe. 利用这个管理器 ...
- Discuz!NT中的Redis架构设计
在之前的Discuz!NT缓存的架构方案中,曾说过Discuz!NT采用了两级缓存方式,即本地缓存+memcached方式.在近半年多的实际运行环境下,该方案经受住了检验.现在为了提供多样式的解决方案 ...
- jquery 单行滚动、批量多行滚动、文字图片翻屏滚动效果代码
jquery单行滚动.批量多行滚动.文字图片翻屏滚动效果代码,需要的朋友可以参考下. 以下代码,运行后,需要刷新下,才能加载jquery,要不然看不到效果.一.单行滚动效果 <!DOCTYPE ...
- 在MFC框架中使用OpenGL的简单实例
引言 我们知道,在MFC框架中,用于绘图的接口是GDI.但GDI只能绘制简单的2D图形,要想制作精美的3D图形,一个可行的办法是使用OpenGL或者Direct3D等第三方库. 由于最近在给导师的一个 ...
- jQuery.Autocomplete实现自动完成功能
一.http://www.w3c.com.cn/jquery-plugin-autocomplete-参数及实例 二.jQuery plugin: Autocomplete 参数 minChars: ...
- Linux PHP实现仿百度文库预览功能
1.安装openoffice: tar zxvf OOo_3.3.0_Linux_x86-64_install-rpm-wJRE_zh-CN.tar.gzcd RPEMrpm -ivh *.rpm安装 ...
- 【转载】grep,egrep,fgrep详解
[转载自]http://blog.csdn.net/homking/article/details/6000711 egrep 等价于 grep -E fgrep 等价于 grep -F grep - ...
- leetcode@ [127] Word Ladder (BFS / Graph)
https://leetcode.com/problems/word-ladder/ Given two words (beginWord and endWord), and a dictionary ...