C++中的异常处理(一)
版权声明:本文为博主原创文章,未经博主允许不得转载。
异常就是运行时出现的不正常,例如运行时耗尽了内存或遇到意外的非法输入。异常存在于程序的正常功能之外,并要求程序立即处理。不能不处理异常,异常是足够重要的,使程序不能继续正常执行的事件。如果找不到匹配的catch,程序就调用库函数terminate。
如果不处理异常将会出现上图的效果。下面是处理异常的代码:
- #include<iostream>
- using namespace std;
- int main()
- {
- try
- {
- int a=3,b=0;
- int c=a/b;
- }
- catch(...)
- {
- }
- return 0;
- }
这里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如下:
- #if !defined(AFX_MYEXCEPTION_H__EB39C92B_B867_41AA_83A6_E614FD4AEC63__INCLUDED_)
- #define AFX_MYEXCEPTION_H__EB39C92B_B867_41AA_83A6_E614FD4AEC63__INCLUDED_
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- #include<string>
- #include<stdexcept>
- class MyException:public std::logic_error
- {
- public:
- MyException(std::string s,std::string myinfo);
- const char* what() const;
- virtual ~MyException();
- private:
- std::string myinfo;
- };
- #endif // !defined(AFX_MYEXCEPTION_H__EB39C92B_B867_41AA_83A6_E614FD4AEC63__INCLUDED_)
MyException.cpp内容如下:
- #include "MyException.h"
- MyException::MyException(std::string s,std::string myinfo):logic_error(s)
- {
- this->myinfo=myinfo;
- }
- MyException::~MyException()
- {
- }
- const char* MyException::what() const
- {
- return myinfo.c_str(); //此处
16. }
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//15行 此处,比较迷惑,在C++代码中常能看到XXX.c_str()类型的代码,经查证,myinfo为string类,string类标准里有c_str函数,该函数作用为返回---> Object字符串 在CPLUSPLUS中返回值描述为下:
std::string::c_str
Returns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C-string) representing the current value of the string object.
返回一个指针指向一个数组,其中包含一个以null结尾的字符序列(即。c字符串)代表字符串对象的当前值。
This array includes the same sequence of characters that make up the value of the string object plus an additional terminating null-character (' ') at the end.
这个数组包含相同的字符序列组成字符串对象的值加上一个额外的终止null字符( 0)。
Return Value
A pointer to the c-string representation of the string object's value.一个指向字符串对象的c字符串表示的值。 ---例子接着看
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
main函数所在的文件内容如下:
- #include<iostream>
- #include"MyException.h"
- using namespace std;
- void getException(bool b)
- {
- if(b)
- {
- throw MyException("error","the parameter is true");
- }
- }
- int main()
- {
- try
- {
- getException(1);
- }
- catch(logic_error &e)
- {
- cout<<e.what()<<endl;
- }
- return 0;
- }
运行结果如下: