第七章:异常处理

  1.C++的异常处理由三个主要的语汇组件构成

  ①一个throw子句。他在程序某处发出一个异常。被抛出的异常可以使内置类型也可以是使用者自定义的类型。

  ②一个或多个catch子句。每一个catch都是一个异常处理器,负责在封闭的区段处理异常

  ③一个try区段。他被围绕以一系列的程序局,这些城数据可能会引发catch子句起作用。

  2.栈展开(stack unwind):当一个异常被抛出时,控制权会从函数调用中释放,并寻找一个吻合的catch语句。当函数调用的控制权被放弃时,存放函数调用的堆栈将会推出pop那个函数(推出之前局部类对象的析构函数会被调用)(当然由编译器完成调用析构的操作)

1 Point* mumble()
2 {
3     Point *pt1,*pt2;
4     pt1=foo();
5     Point p;
6     pt2=foo();
7     ....
8 }

 

  上面的代码中如果第一个foo()产生异常,则unwinding之前不需要调用析构函数,而第二个foo()产生异常时,unwinding之前需要调用Point的析构函数。行2-4和行5-7为两个不同区域,因为异常处理时他们有不同的处理方法。

  3.为了实现将局部对象析构,需要有额外的薄记操作,编译器有两种做法①将两块区域以将被摧毁的局部对象的链表(编译期就被设定好)联合起来②让两块区域共享同一个链表,该链表会在执行期扩大。

  4,new运算符和构造函数抛出异常时,编译器会自动处理未完成的对象和空间。其他情况,需要程序员注意异常情况下的处理(尤其是多线程)可以将资源需求封装在一个类对象内,让析构函数来释放资源。

  5.一个异常如果在本区域没有被catch,则会unwind这个函数,然后进入下一个区域寻找catch

  6.编译器通过构造出程序计数器范围(counter-range)表格来识别抛出异常的位置位于哪一个区域,把程序计数器的起始值和结束值放在一个表格中。try之内的区域只需要unwind,try以外的区域可能会析构局部变量。

  7.为了将异常类型和cathc匹配,编译器必须产生一个类型描述器,对所有异常的类型进行编码并且为每一个catch子句产生一个类型描述器。如果是一个派生类则编码内容必须包含所有基类的类型信息。(私有继承的基类可以在成员函数中被捕捉)

  8.异常对象通常被放置在相同形式的异常数据堆栈中。从throw传给catch的是异常对象的地址、类型描述器以及可能会有的异常对象描述器。

  9.以引用传递的异常对象会被改变,但是以普通传递的异常不会接受任何改变,在catch结束后,会复制最初的那个异常对象。

  10.程序中的异常对象不会直接放到异常堆栈中,而是复制品被构造在异常堆栈中。只有在一个catch子句评估完毕并且知道他不会在抛出异常之后,程序中的异常对象才会被摧毁

mumble()
{
    ...
    errVer.fileName("mumble()");
    throw errVer;        //errVer的复制品被放入异常堆栈
}

 

posted @ 2021-07-02 17:03  放不下的小女孩  阅读(42)  评论(0)    收藏  举报