C++ Primer 学习笔记与思考_11 try..catch语句及相关疑点

来源:互联网 发布:淘宝女鞋正品 编辑:程序博客网 时间:2024/06/13 14:00

    在一个小的程序中,可以用比较简单的方法处理异常,例如用if语句判别除数是否为0,如果是0,则输出一个出错信息。但是在一个大的系统中,包含很多模块,每个模块又包含许多类和函数,函数之间又互相调用,比较复杂。如果在每一个函数中都设置处理异常的程序段,会使程序过于庞大和复杂。因此c++采用的办法是:如果在执行一个函数过程中出现异常,可以不在本函数中立即处理,而是发出一个信息,传给他的上一级(即调用他的函数),他的上机捕捉到这个信息后进行处理。如果上一级的函数也不能处理,就再传给上一级,如此逐级上送,如果还是不存在处理该异常的catch子句,程序的运行就要跳转到名为terminate的标准库函数,该函数在exception头文件中定义。这个标准库函数的行为依赖于系统,通常情况下,它的执行将导致程序非正常退出。

(一)基本语法结构

一般的catch出现的形式是:try{}catch(except1&){}catch(except2&){}catch(...){} //接受所有异常一般都写成引用(except1&),原因很简单,效率。
简单的示例:

#include<iostream>#include<string>using namespace std;int main(){    string ex = "this is a exception";    try    {        cout<<"before throw"<<endl;        throw ex;        cout<<"after throw"<<endl;    }    catch(string &e)    {        cout<<e<<endl;    }    cout<<"end"<<endl;// }
注意,catch中抛出string类型的异常后立即跳出此函数,随后被catch捕捉,执行catch处理后,继续执行catch后的语句,输出"end"。


(二)多个catch捕捉

一个try-catch结构中只能有一个rtry块,但是却可以有多个catch块,以便与不同的异常信息匹配。

int main(){    try    {        cout << "在 try block 中, 准备抛出一个异常." << endl;         //这里抛出一个异常(其中异常对象的数据类型是char*)        char* p=0;         throw p;    }          //catch( char* value )         //注意这里catch语句    catch(...)    {         cout << "在 catch(…) block 中, char*类型的异常对象也被处理" << endl;    }}
catch还有另外一种写法,即除了指定类型名之外,还可以指定变量名,如catch(double d) { cout<<"throw "<<d<<endl; }
catch(...)删节号...代表他可以捕捉到任何类型的异常信息,通常放在try-catch结构的最后。

(三)嵌套的try-catch结构

int main() {    try    {          //这里是嵌套的trycatch结构块          try          {              cout << "在 try block 中, 准备抛出一个int数据类型的异常." << endl;              throw 1;          }          catch( double )          {              cout << "在 catch block 中, double数据类型处理异常错误。"<< endl;          }          cout << "在 try block 中, 准备抛出一个int数据类型的异常." << endl;          throw 0.5;    }     catch( int )     {          cout << "在 catch block 中, int数据类型处理异常错误。"<< endl;     }     return 0; } 
抛出int异常后,要到上一层函数调用中才找到匹配的catch,因此只会输出最后一个catch中的处理数据。

[特别提示]:在C++标准中规定,可以在程序任何地方throw一个异常对象, 并不要求一定只能是在受到try block监控保护的作用域中才能抛出异常, 如果在程序中出现了抛出的找不到对应catch block的异常对象时,C++标准中规定要求系统必须执行terminate()来终止程序。 因此这个例程是可以编译通过的,但运行时却会异常终止。这往往给软件 系统带来了不安全性。与此形成对比的是java中提供的异常处理模型却是不允许出现这样的找不到对应catch block的异常对象,它在编译时就给出错误 ,所以java中提供的异常处理模型往往比C++要更完善。


try-catch的问题解决了,我们再来看一下我在c++ primer的语句这一章找到的两个知识点:

1.悬垂else问题

int main(){int a=0,b=0;if(a<=b)  if(a==b)  a++;elseb++;cout<<a<<" "<<b<<endl;return 0; } 

这个程序表明了所有语言的if语句都普遍存在着潜在的二义性。这种情况往往成为悬垂else问题;上述代码中,看缩进的用法表明else应与外层的if语句相匹配。然而,C++中解决悬垂else问题的二义性的办法 是通过将else匹配给最后出现的尚未匹配的if子句来解决。

所以相当于第一个if的处理是空语句。

2.简洁就是美

  while语句内部数组复制的简洁代码    int arr1[10];    int *source=arr1;    size_t sz=sizeof(arr1)/sizeof(*arr1);    int *dest=new int[sz];    while(source!=arr1+sz)    *dest++=*source++; //简洁,相当于/*    *dest=*source;   ++dest;   ++source; */

可以在for语句的init-statement中定义多个对象,但是不管怎样,该处只能出现一个语句,因此所有的对象必须具有相同的一般类型

for(int ival=0,*pi=ia,&ri=val;ival!=size;++ival,++pi,++ri)

{}  //必须都为int类型




0 0
原创粉丝点击