C++中的异常处理

Posted the_tops ----

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++中的异常处理相关的知识,希望对你有一定的参考价值。

 来自:CSDN 卡尔  后续有C++中的异常处理(二)C++中的异常处理(三)C++中的异常处理(二)是对动态分配内存后内部发生错误情况的处理方法,C++中的异常处理(三)中是使用时的异常说明。都易懂易学,值得读!!

C++中的异常处理(一)

标签: c++C++exceptionException异常处理
技术分享 分类:
 

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

技术分享

 

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

[cpp] view plain copy
 
  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如下:

[cpp] view plain copy
 
  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内容如下:

[cpp] view plain copy
 
  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函数所在的文件内容如下:

[cpp] view plain copy
 
  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的内容。这就是多态在异常中的使用。

以上是关于C++中的异常处理的主要内容,如果未能解决你的问题,请参考以下文章

C++中的异常处理

C++中的异常处理

C++ 中的通用异常处理

通过 SWIG 处理 Java 中的 C++ 异常

C++异常处理的学习笔记

C++中的异常处理(上)