C++学习笔记27:异常处理机制

时间:2022-10-20 15:07:57

一、异常处理机制基础

  异常的定义

    程序中可以检测的运行不正常的情况

  异常处理的基本流程

    某段程序代码在执行操作时发生特殊情况,引发一个特定的异常

    另一段程序代码捕获该异常并处理它

二、异常的引发

throw

三、异常的捕获

try

{

...

}

catch(...)

四、异常类与异常对象

五、异常处理策略

  异常类可以派生和继承,形成类库架构

  可捕获的异常对象的型式

    普通型式(包括类):异常对象需要拷贝

    对某型式对象的引用:没有额外的拷贝动作

    指向某型式对象的指针:要求对象动态构造或者在catch子句中可以访问

catch子句

  • 可以有多个catch子句,每个负责捕获一种,一类或者全部异常
  • 捕获一种:catch(int),catch(const char *)
  • 捕获一类(该类或其派生类异常):catch(const EStackFull &)
  • 捕获全部:catch(...)
  • 所有catch子句按照定义顺序执行,因此派生异常类处理必须定义在基类之前,否则不会被执行

异常再引发

  • 可以在基本任务完成后重新引发所处理的异常
  • 主要用于在程序终止前写入日志和实施特殊的清除任务

try

{

  throw AnException();

}

catch(...)

{

//...

throw;

}

栈展开

  异常引发代码和异常处理代码可能属于不同的函数

  当异常发生时,沿着异常处理块的嵌套顺序逆向查找能够处理该异常的catch子句

  如果找到对应的catch子句,处理该异常

  异常处理完毕后,程序保持catch子句所在的函数栈框架,不会返回引发异常的函数栈框架

  函数栈框架消失时,局部对象被析构,但如果未执行delete操作,动态分配的目标对象未析构

未处理异常

  所有未处理的异常由预定义的std::terminate()函数处理

  可以使用std::set_terminate()函数设置std::terminate()函数的处理例程

void  term_func() { exit(-); }
int main()
{
try
{
set_terminate(term_func);
throw "out of memory!";
}
catch (int)
{
/*...*/
}
return ;
}
//由于catch只能处理整数型的异常,因此字符串型的异常无法处理,交由term_func()函数处理;
//假设没有定义term_func()函数,则所有的无法处理的异常都交由操作系统处理

描述函数是否引发异常

  • 否:throw()
  • 是,引发任意型式的异常:throw(...)
  • 是,引发某类异常:throw(T),部分编译器将其作为throw(...)

C++11规范

  • 否:noexcept,等价于noexcept(true)
  • 是:noexcept(false)
  • 可能:noexcept(noexcept(expr)),expr为可转换为true或false的常数表达式
  • C++11下,建议使用noexcept代替throw

六、异常描述规范

//例子
//类声明时将会引发异常的函数描述清楚
class JuStack
{
public:
int pop() throw(EstackEmpty);
void push(int value)throw(EStackFull);
};