zoukankan      html  css  js  c++  java
  • C++之异常处理

      程序中的错误分为编译时的错误和运行时的错误。编译时的错误主要是语法错误,比如:句尾没有加分号,括号不匹配,关键字错误等,这类错误比较容易修改,因为编译系统会指出错误在第几行,什么错误。而运行时的错误则不容易修改,因为其中的错误是不可预料的,或者可以预料但无法避免的,比如内存空间不够,或者在调用函数时,出现数组越界等错误。如果对于这些错误没有采取有效的防范措施,那么往往会得不到正确的运行结果,程序不正常终止或严重的会出现死机现象。我们把程序运行时的错误统称为异常,对异常处理称为异常处理。C++中所提供的异常处理机制结构清晰,在一定程度上可以保证程序的健壮性。

      C++中处理异常的过程是这样的:在执行程序发生异常,可以不在本函数中处理,而是抛出一个错误信息,把它传递给上一级的函数来解决,上一级解决不了,再传给其上一级,由其上一级处理。如此逐级上传,直到最高一级还无法处理的话,运行系统会自动调用系统函数terminate,由它调用abort终止程序。这样的异常处理方法使得异常引发和处理机制分离,而不在同一个函数中处理。这使得底层函数只需要解决实际的任务,而不必过多考虑对异常的处理,而把异常处理的任务交给上一层函数去处理。

      C++的异常处理机制有3部分组成:try(检查),throw(抛出),catch(捕获)。把需要检查的语句放在try模块中,检查语句发生错误,throw抛出异常,发出错误信息,由catch来捕获异常信息,并加以处理。一般throw抛出的异常要和catch所捕获的异常类型所匹配。异常处理的一般格式为:

      try

      {

        被检查语句

        throw 异常

      }

      catch(异常类型1)

      {

        进行异常处理的语句1

      }

      catch(异常类型2)

      {

        进行异常处理的语句2

      }

      ...

    下面我们用示例演示一下异常处理:

    #include "stdafx.h"
    #include <iostream>
    
    template <typename T>
    T Div(T x,T y)
    {
    if(y==0)
    throw y;//抛出异常
    return x/y;
    }
    
    int main()
    {
    int x=5,y=0;
    double x1=5.5,y1=0.0;
    try
        {
    //被检查的语句
            std::cout<<x<<"/"<<y<<"="<<Div(x,y)<<std::endl;
            std::cout<<x1<<"/"<<y1<<"="<<Div(x1,y1)<<std::endl;
        }
    catch(int)//异常类型
        {
            std::cout<<"除数为0,计算错误!"<<std::endl;//异常处理语句
        }
    catch(double)//异常类型
        {
            std::cout<<"除数为0.0,计算错误!"<<std::endl;//异常处理语句
        }
    
    return0;
    }
    

      

    结果:

    看了上述的示例代码,也许有人会问,第二个双精度类型的除法计算也应该抛出异常才对啊,在实际的运行过程中并非如此,其实该双精度类型除法函数根本没有被执行过。以上程序的执行规程为:调用函数Div(x,y)时发生异常,由函数Div中的语句"throw y"抛出异常,并不在往下执行return x/y,接着catch捕获int类型的异常并处理异常,最后直接执行"return 0"。因此函数Div(x1,y1)和catch(double){}模块根本没有被执行。如果,我们把y的值改为1,则结果就变成为:

    如果在执行try语句模块时,没有发生异常,则catch语句块不起作用,流程转到其后的语句继续执行。从上述两个结果中可知第一次throw抛出的int类型所以找到处理该类型的catch,而第二次是抛出double类型所找到的是处理double类型的catch。

      下面对异常处理补充几点:(1)try和catch块中必须要用花括号括起来,即使花括号内只有一个语句也不能省略花括号;(2)try和catch必须成对出现,一个try_catch结果中只能有一个try块,但可以有多个catch块,以便与不同的异常信息匹配;(3)如果在catch块中没有指定异常信息的类型,而用删节号"...",则表示它可以捕获任何类型的异常信息;(4)如果throw不包括任何表达式,表示它把当前正在处理的异常信息再次抛出,传给其上一层的catch来处理;(5)C++中一旦抛出一个异常,如果程序没有任何的捕获,那么系统将会自动调用一个系统函数terminate,由它调用abort终止程序;

      最后还是一样,我将用一个示例来总结一下今天所讲的内容(开发工具:vs2010): 

    #include "stdafx.h"
    #include <iostream>
    
    template <typename T>
    T Div(T x,T y)
    {
    if(y==0)
    throw y;//抛出异常
    return x/y;
    }
    
    int main()
    {
    int x=5,y=1;
    double x1=5.5,y1=0.0;
    try
        {
    //被检查的语句
            std::cout<<x<<"/"<<y<<"="<<Div(x,y)<<std::endl;
            std::cout<<x1<<"/"<<y1<<"="<<Div(x1,y1)<<std::endl;
        }
    catch(...)//捕获任意类型异常
        {
    try
            {
                std::cout<<"任意类型异常!"<<std::endl;
    throw;//抛出当前处理异常信息给上一层catch
            }
    catch(int)//异常类型
            {
                std::cout<<"除数为0,计算错误!"<<std::endl;//异常处理语句
            }
    catch(double)//异常类型
            {
                std::cout<<"除数为0.0,计算错误!"<<std::endl;//异常处理语句
            }
        
        }
        
    return0;
    }
    

      

    结果:

    当你急着下班跟妹子约会的时候,你会发现try catch其实是个好东西。

  • 相关阅读:
    Roce ofed 环境搭建与测试
    Ubuntu 1804 搭建NFS服务器
    Redhat 8.0.0 安装与网络配置
    Centos 8.1 安装与网络配置
    SUSE 15.1 系统安装
    VSpare ESXi 7.0 基本使用(模板、iso、SRIOV)
    VSpare ESXi 7.0 服务器安装
    open SUSE leap 15.1 安装图解
    KVM虚拟机网卡连接网桥
    GitHub Action一键部署配置,值得拥有
  • 原文地址:https://www.cnblogs.com/7code/p/5047476.html
Copyright © 2011-2022 走看看