- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
异常处理相关内容
参考more effective c++ 条款9~条款15,帖出条款九供参考
5.4 Item M12:理解“抛出一个异常”与“传递一个参数”或“调用一个虚函数”间的差异
从语法上看,在函数里声明参数与在catch子句中声明参数几乎没有什么差别:
class Widget { ... }; //一个类,具体是什么类
// 在这里并不重要
void f1(Widget w); // 一些函数,其参数分别为
void f2(Widget w); // Widget, Widget,或
void f3(const Widget w); // Widget* 类型
void f4(Widget *pw);
void f5(const Widget *pw);
catch (Widget w) ... //一些catch 子句,用来
catch (Widget w) ... //捕获异常,异常的类型为
catch (const Widget w) ... // Widget, Widget, 或
catch (Widget *pw) ... // Widget*
catch (const Widget *pw) ...
你因此可能会认为用throw抛出一个异常到catch子句中与通过函数调用传递一个参数两者基本相同。这
里面确有一些相同点,但是他们也存在着巨大的差异。
让我们先从相同点谈起。你传递函数参数与异常的途径可以是传值、传递引用或传递指针,这是相同的
。但是当你传递参数和异常时,系统所要完成的操作过程则是完全不同的。产生这个差异的原因是:你
调用函数时,程序的控制权最终还会返回到函数的调用处,但是当你抛出一个异常时,控制权永远不会
回到抛出异常的地方。
有这样一个函数,参数类型是Widget,并抛出一个Widget类型的异常:
// 一个函数,从流中读值到Widget中
istream operator(istream s, Widget w);
void passAndThrowWidget()
{
Widget localWidget;
cin localWidget; //传递localWidget到 operator
throw localWidget; // 抛出localWidget异常
}
当传递localWidget到函数operator里,不用进行拷贝操作,而是把operator内的引用类型变量w指
向localWidget,任何对w的操作实际上都施加到localWidget上。这与抛出localWidget异常有很大不同
。不论通过传值捕获异常还是通过引用捕获(不能通过指针捕获这个异常,因为类型不匹配)都将进行
lcalWidget的拷贝操作,也就说传递到catch子句中的是localWidget的拷贝。必须这么做,因为当
localWidget离开了生存空间后,其析构函数将被调用。如果把localWidget本身(而不是它的拷贝)传
递给catch子句,这个子句接收到的只是一个被析构了的Widget,一个Widget的“尸体”。这是无法使
用的。因此C++规范要求被做为异常抛出的对象必须被复制。
即使被抛出的对象不会被释放,也会进行拷贝操作。例如如果passAndThrowWidget函数声明
localWidget为静态变量(static),
void passAndThrowWidget()
{
static Widget localWidget; // 现在是静态变量(static);
//一直存在至程序结束
cin localWidget; // 象以前那样运行
throw localWidget; // 仍将对localWidget
} //进行拷贝操作
当抛出异常时仍将复制出localWidget的一个拷贝。这表示即使通过引用来捕获异常,也不能在catch块
中修改localWidget;仅仅能修改localWidget的拷贝。对异常对象进行强制复制拷贝,这个限制有助于
我们理解参数传递与抛出异常的第二个差异:抛出异常运行速度比参数传递要慢。
当异常对象被拷贝时,拷贝操作是由对象的拷贝构造函数完成的。该拷贝构造函数是对象的静态类型(
static type)所对应类的拷贝构造函数,而不是对象的动态类型(dynamic type)对应类的拷贝构造
函数。比如以下这经过少许修改的passAndThrowWidget:
class Widget { ... };
class SpecialWidget: public Widget { ... };
void passAndThrowWidget()
{
SpecialWidget localSpec
原创力文档


文档评论(0)