处理异常的方法
1 方法一:abort() 直接终止程序,可能会向标准错误流(cerr) 发送信息。
2 方法二:使用特殊的函数返回值(错误码)。
3 方法三:异常机制
try
{
...//可能引发异常的语句
}
catch (const char * s )//捕获异常
{
...//异常处理
}
throw :关键词为抛出异常,为一个类。
catch(bad3& b)
{
...
}
catch(bad2& b)
{
...
}
catch(bad1& b)
{
...
}
catch:捕获顺序,若bad1、bad2、bad3为继承顺序,则这样可以先bad3只能捕获bad3,bad2则是可以捕获bad3和bad2,而最后的bad1则可以捕获所有的bad类。但是派生特性将被剥去,使用的基类的虚方法。注意:catch 的法则类似于函数传参,但是对于即使是引用类型参数,其也总是复制一个临时变量,然后让参数引用来指向该临时变量。注:但是实际测试,其虚方法的特性仍然存在。
catch(...){statement}
使用 …来捕获未知的异常,类似于swtich的default
异常规范:
class problem(){...}
void f() throw (problem)//异常规范,表明这个方法将会抛出一个problem异常
{...}
而使用 noexcept 修饰则为不抛出异常
异常类
异常类层次
-----
| <- domain_error
----- | <- invalid_argument
| <- logic_error | <- length_error
| | <- out_of_range
exception | -----
| | <- range_error
| <- runtime_error | <- overflow_error
----- | <- underflow_error
-----
对于所有的异常类中有一个虚方法const char * what() const
此可以在派生类中覆写。
对于关键字new,若是分配失败,则有对应的异常类 bad_alloc。
迷失的异常
- 未捕获的异常:对于未捕获的异常,程序不会异常终止,而首先会调用 terminate(),而terminate() 将会调用abort()函数终止程序,通过set_teminate()可以修改terminate() 中调用的函数。如下,注意此代码在visual studio中无法正常打印"g()",编译器会提前终止并指出抛出异常未被捕获,但是可以在DevC++中运行。
#include<iostream>
#include <exception>
#include <cstdlib>
using namespace std;
void t()//被terminate调用的函数
{
cout << "t()";
exit(0);
}
class problem{};
void g() throw(problem)//引发异常的函数
{
throw problem();
}
int main()
{
set_terminate(t);//将调用的函数修改
g();
}
- 意外异常:对于可能抛出异常的语句运用了 try语句,但是在catch中没有找到与之匹配的参数类型(包括本类和派生类的基类引用),则这被称为意外异常。
同未捕获的异常一样,它也不会导致程序异常终止,而是调用unexpected() ,而其会调用terminate(),然后terminate() 会默认调用 abort() 终止函数。相同的可以用set_unexpected()来指定unexpected()调用的函数。
最后一点:要注意异常和栈解退,防止内存泄漏。
异常补充:链接: link.