【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 ...
随机推荐
- 【HDOJ】1667 The Rotation Game
1. 题目描述有个#字型的条带,可以从横线或竖线进行循环移动,求通过各种移动最终使中心的8个字符全等的长度最短并相同长度字典序最小的操作序列.2. 基本思路24个数据,8种移动方式,数据量很小了,所以 ...
- Ubuntu忘记管理员密码
Ubuntu中不小心把管理员密码忘记了,真叫人头大. 现提供一个解决方案: 1.重启 Ubuntu 系统,按 Esc 进入GRUB 菜单界面,如下图: 2.选择recovery mode. (第二个) ...
- UVa 1363 (数论 数列求和) Joseph's Problem
题意: 给出n, k,求 分析: 假设,则k mod (i+1) = k - (i+1)*p = k - i*p - p = k mod i - p 则对于某个区间,i∈[l, r],k/i的整数部分 ...
- Sharepoint中用treeview来显示组织机构的人员状态的webpart
转:http://www.cnblogs.com/virusswb/archive/2009/04/28/1445517.html
- Entity Framework Code First级联删除
如果我们要到一对主从表增加级联删除,则要在主表中的引用属性上增加Required关键字,如: public class Destination { public int DestinationId { ...
- Myeclipse最简单的svn插件安装方法
首先来这儿下载插件 http://subclipse.tigris.org/servlets/ProjectDocumentList?folderID=2240 找个最新的下载 解压到对应的位置, ...
- Diamond
Diamond主要提供持久配置的发布和订阅服务,最大特点是结构简单,稳定可靠.Diamond的主要使用场景是用来进行动态数据库切换与扩容,进行一些业务系统运行时开关配置的推送.Diamond产品专注于 ...
- mac 修改xcode的版本
http://blog.csdn.net/yangzhenping/article/details/50266245
- 2014 多校联合训练赛6 Fighting the Landlords
本场比赛的三个水题之一,题意是两个玩家每人都持有一手牌,问第一个玩家是否有一种出牌方法使得在第一回和对方无牌可出.直接模拟即可,注意一次出完的情况,一开始没主意,wa了一发. #include< ...
- python引用在函数传参时的体现以及可变与不可变对象的对比
今天偶然看到 vamei 老师的博客 http://www.cnblogs.com/vamei/archive/2012/07/10/2582795.html 讲的是python动态类型以及引用的事儿 ...