C++ Primer chap11

1

异常使用示例:

try { 

     for ( int ix = 1; ix < 51; ++ix ) 

     { 

         if ( ix % 3 == 0 ) 

             stack.push( ix ); 

         if ( ix % 4 == 0 ) 

             stack.display(); 

         if ( ix % 10 == 0 ) { 

             int dummy; 

             stack.pop( dummy ); 

             stack.display(); 

         } 

     } 

catch ( pushOnFull ) { ... } 

catch ( popOnEmpty ) { ... } 

其中的push, pop 在栈满和空时这样抛出异常:

// 表达式是一个构造函数调用 

throw popOnEmpty(); 

当然,也可以抛出其他类型的对象。

 在我们的例子中 程序的控制流是下列几种情况之一  

        1    如果没有异常发生 则执行try 块中的代码 和try 块相关联的处理代码被忽略 程 

序main()返回0     

        2    如果在for 循环的第一个if 语句中调用的成员函数push()抛出一个异常 则for 循环 

的第二个和第三个if 语句被忽略 该for 循环和try 块被退出 执行pushOnFull 类型异常的 

处理代码  

        3    如果在for 循环的第三个if 语句中调用的成员函数pop()抛出一个异常 则针对display() 

的调用被忽略 for 循环和try 块被退出 执行popOnEmpty 类型异常的处理代码  

        当某条语句抛出异常时 跟在该语句后面的语句将被跳过 程序执行权被转交给处理异 

常的catch 子句 如果没有catch 子句能够处理该异常 则程序执行权又将被转交给C++标准 

库中定义的函数terminate()  。

2

 C++的异常处理机制被称为是不可恢复的  nonresumptive      一旦异常被处理 程序的 

执行就不能够在异常被抛出的地方继续 在我们的例子中 一旦异常被处理 程序的执行就 

不能够在pop()成员函数中异常被抛出的地方继续 

3

 异常对象总是在抛出点被创建 即使throw 表达式不是一个构造函数调用 或者它没有 

表现出要创建一个异常对象 情况也是如此 例如  

enum EHstate { noErr, zeroOp, negativeOp, severeError }; 

enum EHstate state = noErr; 

int mathFunc( int i ) { 

     if ( i == 0 ) { 

         state = zeroOp; 

         throw state; // 创建异常对象 

     } 

     // 否则, 正常处理流程继续 

        在这个例子中 对象state 没有被用作异常对象 而是由throw 表达式创建了一个类型为 

EHstate 的异常对象 并且用全局对象state 的值初始化该对象 

后面catch可以这样用:

void calculate( int op ) { 

     try { 

         mathFunc( op ); 

     } 

     catch ( EHstate &eObj ) { 

         // eObj 是被抛出的异常对象的引用

     } 

4

 throw 表达式的行为有点像函数调用 而catch 子句有点像函数定义 这两种机制的一个主要区别是  

建立函数调用所需要的全部信息在编译时刻已经获得 而对异常处理机制则不然 C++异常 

处理要求运行时刻的支持 

5

如果有一个异常被抛出 则资源res 的释放被跳过去 为保证该资源被释放 我们不是 

为每种可能的异常都写一个catch 子句 因为我们不知道可能被抛出的全部异常 但是我们 

可以使用catch 子句catch-all    这种catch 子句有一个形式为 ...    的异常声明 这里的二个点 

被称为省略号 ellipsis      对任何类型的异常 都会进入这个catch 子句 例如  

// 对任何异常都会进人 

catch ( ... ) { 

     // 这里是我们的代码 

6

在异常处理过程中也可能存在 单个catch 子句不能完全处理异常 的情况 在某些修正动作之后 catch 子句

可能决定该异常必须由函数调用链中更上级的函数来处理 那么catch子句可以通过重新抛出  rethrow   

 该异常 把异常传递给函数调用链中更上级的另一个catch 子句 

rethrow 表达式的形式为  

throw; 

        rethrow 表达式重新抛出该异常对象 rethrow 只能出现在catch 子句的复合语句中 例 

如  

catch ( exception eObj ) { 

     if ( canHandle( eObj ) ) 

         // 处理异常 

         return; 

     else 

         // 重新抛出它, 并由另一个 catch子句来处理 

         throw; 

被重新抛出的异常就是原来的异常对象 

7 异常规范  exception specification    提供 

了一种方案 它能够随着函数声明列出该函数可能抛出的异常 它保证该函数不会抛出任何 

其他类型的异常  

        异常规范跟随在函数参数表之后 它用关键字throw 来指定 后面是用括号括起来的异 

常类型表 例如 我们可以如下修改iStack 类的成员函数的声明 以增加适当的异常规范  

class iStack { 

public: 

     // ... 

     void pop( int &value ) throw(popOnEmpty); 

     void push( int value ) throw(pushOnFull); 

private: 

     // ... 

}; 

        对于pop()的调用 保证不会抛出任何popOnEmpty 类型之外的异常 

原文地址:https://www.cnblogs.com/liujiahi/p/2196380.html