c++ primer异常处理(1)

来源:互联网 发布:淘宝关键词排名优化 编辑:程序博客网 时间:2024/05/22 10:53

             异常就是程序运行时出现的不正常,例如运行时耗尽了内存或遇到意外的非法输入. 异常存在于程序的正常功能之外,并要求程序立即处理. 异常机制提供程序中错误检测错误处理部分之间的通信. c++的异常处理中包括:

              throw表达式 :  错误检测部分使用这种表达式来说明遇到了不可处理的错误.可以说,throw引发了异常条件.

              try块:  错误处理部分使用它来处理异常. try语句块以try关键字开始,并以一个或多个catch字句结束. 在try块中执行的代码所抛出的异常,通常会被其中一个catch字句处理.由于它们"处理"异常,catch字句也称处理代码.

             由标准库定义的一组异常类,用来在throw和相应的catch之间传递有关的错误信息.


throw表达式

         系统通过throw表达式抛出异常.throw表达式由关键字throw以及尾随的表达式组成, 通常以分号结束, 这样它就成为了表达式语句. throw表达式的类型决定了所抛出异常的类型.

以一个计算两个数的调和平均数的函数为例

       

double hmean ( double a, double b ){   if ( a == -b )   {       std::cerr<<"untenable arguments to hmean()\n";       return ;     }   return  2.0*a*b/(a+b);}

上面的代码中,如果a == -b;则立刻输出错误提示, 并结束程序. 该代码可以用throw抛出异常来改写,如下

double hmean ( double a, double b ){   if ( a == -b )       throw runtime_error(" untenable arguments to hmean()");    return 2.0*a*b / (a+b);}

 throw语句使用了一个表达式,该表达式是runtime_error类型的对象.rumtime_error类型是标准库异常类中的一种,在stdexcept头文件中定义. 可以测试一下这个程序.

#include <stdexcept>#include <iostream>using namespace std;int main(){   double a,b,c;   while(1)   {   cout<<"输入a和b: ";   cin>>a>>b;   try {        c=hmean(a,b);        cout<<a<<"和"<<b<<"的调和平均数为: "<<c<<endl;       }  catch (runtime_error err) {
        cout<<err.what()<<"\nTry again? Enter y or n"<<endl;           char c;          cin>>c;          if( c == 'n' )            break;         }      }
     return 0;
}

what是rumtime_error 类的一个成员函数, 每一个标准库异常类都定义了名为what的成员函数,这个函数不需要参数,返回C风格字符串.在出现runtime_error的情况下,what返回的C风格字符串,是用于初始化runtime_error的string对象的副本.


try块

try块的通用语法形式是:

try {

        program-statements

} catch ( exception-specifier) {

         handler-statements

}  catch ( exception-specifier) {

        handler-statements

} //...


try块以关键字try开始,后面是用花括号括起来的语句序列块.try块后面是一个或多个catch子句. 每个catch子句包括三部分 : 关键字catch,圆括号内单个类型或者单个对象的声明------称为异常说明符,以及通常用花括号括起来的语句块.如果选择了一个catch子句来处理异常,则执行相关的块语句.一旦catch子句执行结束,程序流程立即执行紧随着最后一个catch子句的语句.

   try语句内program-statement形成程序的正常逻辑.这里面可以包含任意c++语句,包括变量声明.与其他块语句一样,try块引入局部作用域,在try块中声明的变量,包括catch子句中声明的变量,不能在try外面引用.


函数在寻找处理代码的过程中退出

   抛出一个异常时,首先搜索的是抛出异常的函数.如果没有找到匹配的catch,则终止这个函数的执行,并在调用这个函数的函数中寻找相配的catch.如果仍然没有找到匹配的catch,则终止这个函数的执行,搜索调用它的函数.如此类推,继续按执行路径回退,直到找到适当类型的catch为止.

   如果不存在处理该异常的catch子句,程序的运行就要跳转到名为terminate的标准库函数,该函数在excepttion头文件中定义.这个标准库函数的行为依赖于系统,通常情况下,他的执行将导致程序非正常退出.


标准异常

c++标准库定义了一组类,用于报告在标准库中函数遇到的问题. 标准库异常定义在四个头文件中:

(1) exception头文件定义了最常见的异常类,它的类名是exception.这个类只通知异常的产生,但不会提供更多的信息.

(2)stdexcept头文件定义了几种常见的异常类

(3)new头文件定义了bad_alloc异常类型,提供因无法分配内存而由new抛出的异常.

(4)type_info头文件定义了bad_cast异常类型.

                                        

在<stdexcept>头文件中定义的标准异常类

exception                                       最常见的问题

runtime_error                                 运行时错误: 仅在运行时才能检测到的问题

range_error                                    运行时错误:  生成的结果超出了有意义的值域范围

overflow_error                                运行时错误: 计算上溢

underflow_error                              运行时错误: 计算下溢

logic_error                                       逻辑错误: 可以在运行前检测到的问题

domain_error                                  逻辑错误: 参数的结果值不存在

invalid_argument                            逻辑错误:  不合适的参数

length_error                                     逻辑错误:  试图生成一个超出该类型最大长度的对象

out_of_range                                   逻辑错误:   使用一个超出有效范围的值


标准库异常类

  标准库异常类只提供很少的操作, 包括创建,复制异常类型对象以及异常类型对象的赋值. exception, bad_alloc以及bad_cast类型只定义了默认构造函数, 无法在创建这些类型对象时为它们提供初值. 其他的异常类型则只定义了一个使用string初始化式的构造函数,当需要定义这些异常类型的对象时,必须提供一个string参数. string初始化式用于为所发生的错误提供更多的信息.

   异常类型只定义了一个名为what的操作.这个函数不需要任何参数,并且返回const char* 类型的值. 它返回的指针指向一个C风格字符串.使用c风格字符串的目的是为所抛出的异常提供更详细的文字描述.


assert预处理宏

assert宏是在cassert头文件中定义的,所有使用assert的文件都必须包含这个头文件.

预处理宏有点像函数调用. assert宏需要一个表达式作为它的条件:

assert(expr)

如果expr的结果为false,assert输出信息并且终止程序的执行.如果该表达式有一个非0值,则assert不做任何操作.一般使用assert来测试"不可能发生"的条件.


0 0
原创粉丝点击