zoukankan      html  css  js  c++  java
  • C++ Primer 有感(异常处理)(二)

    异常就是运行时出现的不正常,例如运行时耗尽了内存或遇到意外的非法输入。异常存在于程序的正常功能之外,并要求程序立即处理。不能不处理异常,异常是足够重要的,使程序不能继续正常执行的事件。如果找不到匹配的catch,程序就调用库函数terminate。

     

    如果不处理异常将会出现上图的效果。下面是处理异常的代码:

    1. #include<iostream>  
    2. using namespace std;  
    3. int main()  
    4. {  
    5.     try  
    6.     {  
    7.     int a=3,b=0;  
    8.     int c=a/b;  
    9.     }  
    10.     catch(...)  
    11.     {  
    12.     }  
    13.   
    14.     return 0;  
    15. }  


    这里catch后圆括号中的...指的是捕获所有异常。

     

    抛出异常的时候,将暂停当前函数的执行,开始查找匹配的catch子句。首先检查throw本身是否在try块内部,如果是,检查与该try相关的catch子句,看是否其中之一与被抛出对象相匹配。如果找到匹配的catch,就处理异常:如果找不到,就退出当前函数(释放当前函数的内存并撤销局部对象),并继续在调用函数中查找。

     

    如果对抛出异常的函数调用是在try块中,则检查与该try块相关的catch子句。如果找到匹配的catch就处理异常;如果找不到匹配的catch,调用函数也退出,并且继续在调用这个函数的函数中查找。

     

    这个过程称之为栈展开,沿嵌套函数调用链继续向上,直到为异常找到一个catch子句。只要找到能够处理异常的catch子句,就进入该catch子句,并在该处理代码中继续执行。当catch子句结束的时候,在紧接在与该try块相关的最后一个catch子句之后的点继续执行。

     

    在栈展开的时候,会退出某个函数,释放当前内存并撤销局部对象,这时会调用对象的析构函数,如果析构函数抛出异常,将会调用标准库terminate函数,强制整个程序非正常退出。所以析构函数应该从不抛出异常。

     

     

    在查找匹配的catch期间,找到的catch不必是与异常最匹配的那个catch,相反,将选中第一个找到的可以处理该异常的catch。因此,在catch子句列表中,最特殊的catch必须最先出现,否则没有执行的机会。

     

    进入catch的时候,用异常对象初始化catch的形参。因为基类的异常说明符可以捕获派生类的异常对象。如果异常对象是引用,则可以使用多态,调用基类的virtual将执行派生类的覆盖的函数。若catch的异常说明符是对象,则将派生类对象分割为它的基类对象。

     

    异常的层次

    异常的层次如下图:


    exception类型所定义的唯一操作是一个名为what的虚成员,该函数返回const char* 对象,它一般返回用来在抛出位置构造异常对象的信息。因为what是虚函数,如果捕获了基类类型的引用,对what函数的调用将执行适合异常对象的动态类型的版本。

    使用自定义异常

     

    下面自定义异常类,继承自logic_error,MyException.h如下:

    1. #if !defined(AFX_MYEXCEPTION_H__EB39C92B_B867_41AA_83A6_E614FD4AEC63__INCLUDED_)  
    2. #define AFX_MYEXCEPTION_H__EB39C92B_B867_41AA_83A6_E614FD4AEC63__INCLUDED_  
    3.   
    4. #if _MSC_VER > 1000  
    5. #pragma once  
    6. #endif // _MSC_VER > 1000  
    7. #include<string>  
    8. #include<stdexcept>  
    9. class MyException:public std::logic_error    
    10. {  
    11. public:  
    12.     MyException(std::string s,std::string myinfo);  
    13.     const char* what() const;  
    14.     virtual ~MyException();  
    15. private:  
    16.     std::string myinfo;  
    17.       
    18.   
    19. };  
    20.   
    21. #endif // !defined(AFX_MYEXCEPTION_H__EB39C92B_B867_41AA_83A6_E614FD4AEC63__INCLUDED_)  


    MyException.cpp内容如下:

    1. #include "MyException.h"  
    2.   
    3. MyException::MyException(std::string s,std::string myinfo):logic_error(s)  
    4. {  
    5.     this->myinfo=myinfo;  
    6. }  
    7.   
    8. MyException::~MyException()  
    9. {  
    10.   
    11. }  
    12.   
    13. const char* MyException::what() const  
    14. {  
    15.     return myinfo.c_str();   
    16. }  


    main函数所在的文件内容如下:

    1. #include<iostream>  
    2. #include"MyException.h"  
    3. using namespace std;  
    4.   
    5. void getException(bool b)  
    6. {  
    7.     if(b)  
    8.     {  
    9.         throw MyException("error","the parameter is true");  
    10.     }  
    11. }  
    12.   
    13. int main()  
    14. {  
    15.     try  
    16.     {  
    17.         getException(1);  
    18.     }  
    19.     catch(logic_error &e)  
    20.     {  
    21.         cout<<e.what()<<endl;  
    22.     }  
    23.     return 0;  
    24. }  


    运行结果如下:

     

    在MyException类中,覆盖了logic_error类中的virtual函数,在catch异常说明类型使用的是基类logic_error的引用,所以输出的结果是MyException中myinfo的内容。这就是多态在异常中的使用。


  • 相关阅读:
    Android Studio 配置Gradle总结
    ion-icon
    Centos 7下利用crontab定时执行任务详解
    Centos7 下安装以及使用mssql
    Docker容器
    linux centos7--linux和window共享文件(samba)
    一些CMS网站系统漏洞,练手用(持续更新)
    相应的游戏服务器组件信息不存在,房间创建失败
    [Windows] php开发工具,zendstudio13使用方法补丁
    mysql sql语句大全
  • 原文地址:https://www.cnblogs.com/wangfengju/p/6173010.html
Copyright © 2011-2022 走看看