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

    在一个小的程序中,可以用比较简单的方法处理异常,例如用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++;
	else
	b++;
	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类型




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值