异常处理
错误
- 语法错误:编译器解决
- 逻辑错误:测试解决
异常
- 运行环境造成。如内存不足、文件操作失败等
- 特征
- 可以预见
- 无法避免
- 异常处理:提高程序鲁棒性
异常处理方法
传统的方法是,使用函数参数或者返回值来标识是否发生异常、发生什么异常。
函数调用者检查参数或者返回值来确定异常,并处理异常。
这样需要逐层返回。并且对于一些特殊的情况无法处理,比如构造函数发生异常。
C++ 异常处理机制
try
监控语句序列中是否发生异常。
try{
statements to monitor
}
throw
try 中检测到异常时,抛出异常。
throw expression
catch
捕获异常并处理。try 后可以跟随多个 catch 来捕获不同类型的异常。
catch (ExceptionType e){
deal with exception...
}
异常处理的嵌套
抛出的异常会在调用链中自下往上捕获。
最终还未被捕获的异常,由系统的 abort 处理。
异常类间的继承
在捕获一系列有继承关系的异常类对象的时候,需要注意:
- 用引用传递异常对象。
即:
try
{...}
catch(Exception1 &e1){...}
catch(Exception2 &e2){...}
如果直接传异常对象,容易发生对象切片。
class EBase {};
class EDerived: public EBase {};
void f(EBase e) {
throw e;
}
EDerived e;
try {
f(e); // Object Slicing, throwing EBase instead of EDerived
}
catch(EDerived e) { cout<<"Derived"; }
catch(EBase e) { cout<<"Base"; } // e caught here
- 按 “从最派生的类到最基的类” 的顺序来捕获
catch 是按声明顺序捕获的。
派生类对象可以被基类的 catch 捕获。
基类在前面的话,后面的派生类会无法捕获。
无参数 throw
将捕获到的异常对象重新抛掷出去
catch(int) { throw; }