关于C++异常处理
#include<iostream>usingnamespacestd;intmain(){try{for(chari='1';i<'5';i++){switch(i){...
#include<iostream>
using namespace std;
int main()
{
try{
for(char i='1';i<'5';i++)
{
switch(i)
{
case'1':
case'2':cout<<i<<endl;break;
case'3':cout<<i<<endl;
throw 10;
case'4':cout<<i<<endl;
default:cout<<"default"<<endl;
throw i;
}
}
}
catch(int exp)
{
cout<<exp<<endl;
}
catch(char exp)
{
cout<<exp<<endl;
}
}
输出是:
1
2
3
10
不明白为什么输出是这个,求解释过程 展开
using namespace std;
int main()
{
try{
for(char i='1';i<'5';i++)
{
switch(i)
{
case'1':
case'2':cout<<i<<endl;break;
case'3':cout<<i<<endl;
throw 10;
case'4':cout<<i<<endl;
default:cout<<"default"<<endl;
throw i;
}
}
}
catch(int exp)
{
cout<<exp<<endl;
}
catch(char exp)
{
cout<<exp<<endl;
}
}
输出是:
1
2
3
10
不明白为什么输出是这个,求解释过程 展开
展开全部
这里边理解两个程序控制单词就可以了!
第一个是break;break是跳出,打断的意思,它经常用在循环或多重分支结构中,表示跳出当前结构,要注意break中的解释是跳出当前结构——并没有说是跳出循环(循环是结构的一种,而多分支结构也是结构的一种),所以用break跳出的是当前结构——也就是说在你的程序中的break跳出的是多重分支持结构,并没有跳出循环。多分支与单分支结构是有区别的,如果break出现在if..else结构中,则跳出的不是双(单)分支结构。所以break在switch内跳出的是switch的结构。switch与if..else if等的构成并不相同,其case分支并没有跳出,也就是说为了方便我们处理多种相同情况下,case分支并不象if分支一样存在隐藏的跳出。比如:
case 1:
case 5:
//other code
这种情况下我们发现某支依据不同,但处理方式相同时,可以直接写成以上类似的方式,这样可以让分支依据为1或5时处理代码不重复,所以分支下要有break时才会直接正的跳出,否则会继承执行。
case 1:
// other code;
case 2:
// other code;
break;
以上的代码就表示,当分支依据为1时,执行完case 1的处理后会继承执行case 2的分支。
第二个单词是throw,这个是我们经常用来自定义例外(Exception,不是错误,在英文中warnning,flaut,error,exception有很大区别的,要理解自定义例外必须要先区别这么单词),自定义抛出例外用的就是throw关键词!这个要考虑到一个例外的冒泡机制,所谓的冒泡机制是与程序没有关系的,与运行时有关,换句话从宏观来说,throw自定义的例外还是运行的例外,都是这种在运行时态体现的东西,它的抛出与你的程序结构没有任何关联性,它在运行时直接抛出——通过冒泡机制一直向外抛出,在代码段中抛出直到遇到try的例外机制,没有没有这个机制,会直接导致程序运行态溃掉——例外捕捉机制会捕捉到其监控的运行块,以保证捕捉机制外的运行块不受影响!微观上讲,例外机制实际上是存在一个运行栈的,而例外抛出则是通过代码栈,冒泡到整体的运行程序,而这个运行程序可能会在该块有监控。
例外机制再换句话来说,try/tryf其实与throw并没有任何关系,即使没有throw,也可能会出现除0等例外的,try/tryf只负责对例外的捕捉。而除0或是你自定的例外则是只管抛出,所以有一种错误的理解可以帮助你——你可以认为throw是抛出到程序外或抛出到显式或隐式的try/tryf结构。如果你非把throw当一种跳出,你可以认为他是一种特殊的“跳出”结构,throw的意思是——所有代码都别“活了”,我要让整个运行的应用“宕”掉!事实上例外就是这么干的——可以try/tryf的作用就是增加应用程序的鲁棒性,所以try/tryf管理或限制着所有的例外(exception),try/tryf不允许例外胡来,所以如果你没有好好设计程序时,最内层的try/tryf最先捕捉到例外(事实上代码监控是有性能代价的——如果正常运行通过,代价并不大,如果一旦发生冒泡,性能损失非常厉害,所以我们在设计程序时有两种方式,但多数时间内不允许发生try/tryf的嵌套,这个问题一会再扩充)。所以根据你的问题,
所以当你的程序值为1时,执行的是1,2合并分支(case 1后没有break会继承执行),但case 2后有break,所以不会再向下执行分支结构(break跳出的是当前结构,并不是循环)。同理,当分支依据为2时,也会执行1,2合并分支,当然因为有break,会输出2。当为3时,执行是case 3分支,会输出3,虽然没有break,但是由于throw,把整个程序溃掉了。try/tryf结构会捕捉到例外。当然try/tryf还有另一个功能,就是结例外类型进行了分类,为按类进行分类,允许使用多重分类的catch块。从而进入到相应的块中。所以它在输出3之后,溃掉整个程序(提代了10的参数),因为被try/tryf捕捉到,所以执行了相应类型的catch分支,当然了,在case分支内输出了参数10。
这里还要解释一下catch例外分类,其实他就是一个语法糖——就是为了你更好的书写代码或阅读或理解代码而已!其实我们有时并不会使用这种例外分类,尤其在有多重需要的时候。例外你以上的处理:
try{
// code in control;
}catch(exception e)
{
if(e is int)
//other code
else
// other code
}
对的,其实你真正的多重catch分类,也是这么干的!
接一下那个扩展问题,说一下例外的两重方式:
第一种方式:建立性能与安全双版本函数。比如int.Parse()就是一个性能版本的,如果你输入的参数有问题,就完全可能出现例外,导致整个程序被抛出。而另一个版本int.TryParse()就是一个安全版本,它两个的作用完全相同,但是,安全版本并不会抛出错误。很多时候当我们看到TryXXX()方式时,往往就是XXX()方法的安全版本。
第二种方式:测试方案函数。比如在某些转换执行时,有一个同名的CanXXXX()的检测方案。CanXXXX()执行结果如果是true就是检测通过,否则检测不通过。这类方法也是比比皆是。
两种方法的方案的区别在于Can是用来测试,而Try其实代码存在有try/tryf结构——不要把Try理解为“试”,其实它表示内部存在try/tryf。can理解为能否,这个很容易理解。还是一个类型测试is不在此列,与这两种方案没有关系(虽然它是测试,但与can测试是两码事)。
那么有以上两种方案之后,我所一般情况下在一个运行程序的独立模块内才会使用try/tryf时有一个特殊的规则——出于性能原因,try/tryf不能够显式或隐式的嵌套(当然,嵌套不会在语言层面上出现任何问题),显式嵌套比如在try/catch/finally任何一个块中不能再有try/tryf结构。隐式嵌套指的是某个方法中存在try/tryf结构,另一个调用方法中也有try/tryf结构,并在try块内调用(安全版本不被认为是try结构,有时成员安全版本中其实是调用了检测方案)。当然,有一个很明显的规就是在catch块内使用throw(想想吧,这种情况就是要求外层还有一重try/tryf结构。所以throw不会出现显式出现在try/tryf的任何一个块中!throw在try块中有特殊的目的似乎是一种理由——但事实上通过性能损失才达到目的就不是什么好的理由!当然了,你这里除外——你这个只是为了演示而已!
有正常的代码中一个方法中多数时间是不会存在try/tryf结构的,但可会存在多个throw,这种设计的目的,就是例外集中处理。绝对不要出现接力例外的情况(除非是核心有特殊目的,但也应该慎之又慎),比如catch块内出现throw,引入新的例外,并把原例外也通过exception的innerexption携带出去。这种情况并不多见。
应用程序员的代码中,如果一个方法中出现try/tryf又出现throw,不管throw是否在try/tryf结构内还是外,代码绝对是垃圾(架构层若是出现,可能是设计师的无奈,不管有奈无奈,都是不好的代码)!
程序上的事给你解释完了,又告诉你一个普真(普遍真理):很多知识其实是在课本外!
第一个是break;break是跳出,打断的意思,它经常用在循环或多重分支结构中,表示跳出当前结构,要注意break中的解释是跳出当前结构——并没有说是跳出循环(循环是结构的一种,而多分支结构也是结构的一种),所以用break跳出的是当前结构——也就是说在你的程序中的break跳出的是多重分支持结构,并没有跳出循环。多分支与单分支结构是有区别的,如果break出现在if..else结构中,则跳出的不是双(单)分支结构。所以break在switch内跳出的是switch的结构。switch与if..else if等的构成并不相同,其case分支并没有跳出,也就是说为了方便我们处理多种相同情况下,case分支并不象if分支一样存在隐藏的跳出。比如:
case 1:
case 5:
//other code
这种情况下我们发现某支依据不同,但处理方式相同时,可以直接写成以上类似的方式,这样可以让分支依据为1或5时处理代码不重复,所以分支下要有break时才会直接正的跳出,否则会继承执行。
case 1:
// other code;
case 2:
// other code;
break;
以上的代码就表示,当分支依据为1时,执行完case 1的处理后会继承执行case 2的分支。
第二个单词是throw,这个是我们经常用来自定义例外(Exception,不是错误,在英文中warnning,flaut,error,exception有很大区别的,要理解自定义例外必须要先区别这么单词),自定义抛出例外用的就是throw关键词!这个要考虑到一个例外的冒泡机制,所谓的冒泡机制是与程序没有关系的,与运行时有关,换句话从宏观来说,throw自定义的例外还是运行的例外,都是这种在运行时态体现的东西,它的抛出与你的程序结构没有任何关联性,它在运行时直接抛出——通过冒泡机制一直向外抛出,在代码段中抛出直到遇到try的例外机制,没有没有这个机制,会直接导致程序运行态溃掉——例外捕捉机制会捕捉到其监控的运行块,以保证捕捉机制外的运行块不受影响!微观上讲,例外机制实际上是存在一个运行栈的,而例外抛出则是通过代码栈,冒泡到整体的运行程序,而这个运行程序可能会在该块有监控。
例外机制再换句话来说,try/tryf其实与throw并没有任何关系,即使没有throw,也可能会出现除0等例外的,try/tryf只负责对例外的捕捉。而除0或是你自定的例外则是只管抛出,所以有一种错误的理解可以帮助你——你可以认为throw是抛出到程序外或抛出到显式或隐式的try/tryf结构。如果你非把throw当一种跳出,你可以认为他是一种特殊的“跳出”结构,throw的意思是——所有代码都别“活了”,我要让整个运行的应用“宕”掉!事实上例外就是这么干的——可以try/tryf的作用就是增加应用程序的鲁棒性,所以try/tryf管理或限制着所有的例外(exception),try/tryf不允许例外胡来,所以如果你没有好好设计程序时,最内层的try/tryf最先捕捉到例外(事实上代码监控是有性能代价的——如果正常运行通过,代价并不大,如果一旦发生冒泡,性能损失非常厉害,所以我们在设计程序时有两种方式,但多数时间内不允许发生try/tryf的嵌套,这个问题一会再扩充)。所以根据你的问题,
所以当你的程序值为1时,执行的是1,2合并分支(case 1后没有break会继承执行),但case 2后有break,所以不会再向下执行分支结构(break跳出的是当前结构,并不是循环)。同理,当分支依据为2时,也会执行1,2合并分支,当然因为有break,会输出2。当为3时,执行是case 3分支,会输出3,虽然没有break,但是由于throw,把整个程序溃掉了。try/tryf结构会捕捉到例外。当然try/tryf还有另一个功能,就是结例外类型进行了分类,为按类进行分类,允许使用多重分类的catch块。从而进入到相应的块中。所以它在输出3之后,溃掉整个程序(提代了10的参数),因为被try/tryf捕捉到,所以执行了相应类型的catch分支,当然了,在case分支内输出了参数10。
这里还要解释一下catch例外分类,其实他就是一个语法糖——就是为了你更好的书写代码或阅读或理解代码而已!其实我们有时并不会使用这种例外分类,尤其在有多重需要的时候。例外你以上的处理:
try{
// code in control;
}catch(exception e)
{
if(e is int)
//other code
else
// other code
}
对的,其实你真正的多重catch分类,也是这么干的!
接一下那个扩展问题,说一下例外的两重方式:
第一种方式:建立性能与安全双版本函数。比如int.Parse()就是一个性能版本的,如果你输入的参数有问题,就完全可能出现例外,导致整个程序被抛出。而另一个版本int.TryParse()就是一个安全版本,它两个的作用完全相同,但是,安全版本并不会抛出错误。很多时候当我们看到TryXXX()方式时,往往就是XXX()方法的安全版本。
第二种方式:测试方案函数。比如在某些转换执行时,有一个同名的CanXXXX()的检测方案。CanXXXX()执行结果如果是true就是检测通过,否则检测不通过。这类方法也是比比皆是。
两种方法的方案的区别在于Can是用来测试,而Try其实代码存在有try/tryf结构——不要把Try理解为“试”,其实它表示内部存在try/tryf。can理解为能否,这个很容易理解。还是一个类型测试is不在此列,与这两种方案没有关系(虽然它是测试,但与can测试是两码事)。
那么有以上两种方案之后,我所一般情况下在一个运行程序的独立模块内才会使用try/tryf时有一个特殊的规则——出于性能原因,try/tryf不能够显式或隐式的嵌套(当然,嵌套不会在语言层面上出现任何问题),显式嵌套比如在try/catch/finally任何一个块中不能再有try/tryf结构。隐式嵌套指的是某个方法中存在try/tryf结构,另一个调用方法中也有try/tryf结构,并在try块内调用(安全版本不被认为是try结构,有时成员安全版本中其实是调用了检测方案)。当然,有一个很明显的规就是在catch块内使用throw(想想吧,这种情况就是要求外层还有一重try/tryf结构。所以throw不会出现显式出现在try/tryf的任何一个块中!throw在try块中有特殊的目的似乎是一种理由——但事实上通过性能损失才达到目的就不是什么好的理由!当然了,你这里除外——你这个只是为了演示而已!
有正常的代码中一个方法中多数时间是不会存在try/tryf结构的,但可会存在多个throw,这种设计的目的,就是例外集中处理。绝对不要出现接力例外的情况(除非是核心有特殊目的,但也应该慎之又慎),比如catch块内出现throw,引入新的例外,并把原例外也通过exception的innerexption携带出去。这种情况并不多见。
应用程序员的代码中,如果一个方法中出现try/tryf又出现throw,不管throw是否在try/tryf结构内还是外,代码绝对是垃圾(架构层若是出现,可能是设计师的无奈,不管有奈无奈,都是不好的代码)!
程序上的事给你解释完了,又告诉你一个普真(普遍真理):很多知识其实是在课本外!
展开全部
case '1'时输出1,case '2'时输出2,case '3'时输出3,然后抛出int异常10,被catch(int exp)捕获到,输出异常信息10。
更多追问追答
追问
为什么case1输出1呢。case2才是1不是嘛?还有case4为什么不执行呢?
追答
case语句没有break会一直向下执行,你学到异常了还问这种问题,说明你该回去复习基础了。
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
airborne troop. It was n
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询