C++异常处理小例

 
学习程序的好方法是阅读代码和改进代码。
下面的程例来自《An Overview of the C++ Programming Language》(5.1 异常和错误处理)
程序用途:使用C++的异常机制,报告stack的上溢或者下溢。(我适当的把代码补全。)

version 1 演示了基本的异常用法。
从try里抛出一个异常(实例或对象),由catch里的类接受。

 1  version  1
 2  //  From: An Overview of the C++ Programming Language
 3   
 4  #include  < cstdlib >
 5  #include  < iostream >
 6  #include  < string >
 7  using   namespace  std;
 8 
 9  template < class  T > class  Stack{
10      T *  v;
11       int  max_size;
12       int  top;
13  public :
14       class  Underflow{ };    //  下溢
15       class  Overflow{ };     //  上溢
16       //  construct function. determine the size   
17      Stack( int  s): max_size(s), top( 0 ){ v  =   new  T[max_size];}      
18       ~ Stack(){}
19       void  push(T c){
20           if (top  ==  max_size)  throw  Overflow();
21          v[top ++ =  c;
22      }
23      T pop(){
24           if (top  ==   0 throw  Underflow();
25           return  v[ -- top];
26      }
27  }; 
28 
29  void  f()
30  {
31      Stack < string >  ss( 10 );
32       try {
33          ss.push( " Quiz " );
34           string  s  =  ss.pop();
35          ss.pop();
36      }
37       catch (Stack < string > ::Overflow){
38          cerr  <<   " error: stack overflow "   <<  endl;
39      }
40       catch (Stack < string > ::Underflow){
41          cerr  <<   " error: stack underflow "   <<  endl;
42      }
43  }
44 
45  int  main( int  argc,  char   * argv[])
46  {
47      f();
48      system( " PAUSE " );
49       return  EXIT_SUCCESS;
50  }
51 
52  输出结果:error: stack underflow
53 
54 


改进,我们的第二个版本如下:
如果将

 1    class  Underflow{ };    //  下溢
 2       class  Overflow{ };     //  上溢
 3 
 4       catch (Stack < string > ::Overflow){
 5          cerr  <<   " error: stack overflow "   <<  endl;
 6      }
 7       catch (Stack < string > ::Underflow){
 8          cerr  <<   " error: stack underflow "   <<  endl;
 9      }
10 


分别改成如下:

 1 
 2       class  Underflow{       //
 3       public :
 4           void  error( void ){
 5              cerr  <<   " stack Underflow "   <<  endl;
 6          }    
 7      };   
 8       class  Overflow{        //  
 9       public :
10           void  error( void ){
11              cerr  <<   " stack Overflow "   <<  endl;
12          } 
13      };   
14 
15       catch (Stack < string > ::Overflow &  e){
16          e.error();
17      }
18       catch (Stack < string > ::Underflow &  e){
19          e.error();
20      }
21 

改后的程序和原先的区别在哪里,看出来了吗? 呵呵呵。

当然,我们还能将代码改进。这样产生了第三个版本。

第三个版本:version3
在Stack里面添加一个类class Stack_error,让Underflow和Overflow都继承它:

 1  template < class  T > class  Stack{
 2       //      
 3  public :
 4       class  stack_error{
 5       public :
 6           virtual   void  error( void ){   // 当然,可以把它做成纯虚的。抽象类。
 7              cerr  <<   " stack_error "   <<  endl;
 8          }
 9      };
10       class  Underflow:  public  stack_error{       //
11       public :
12           void  error( void ){
13              cerr  <<   " stack Underflow "   <<  endl;
14          }    
15      };   
16       class  Overflow:  public  stack_error{        //  
17       public :
18           void  error( void ){
19              cerr  <<   " stack Overflow "   <<  endl;
20          } 
21      };   
22       //  
23  }
24 
接着把两个catch合并成一个catch,如下。
   try {
     
//  the same
    }
    
catch (Stack < string > ::stack_error &  e){
        e.error();
    }

这三个版本的功能是一样的,但版本越高,代码越清晰,代码也越容易维护。

如果我们设计了一个库(比如上面的Stack),在开始的时候想到的就是两个异常,overflow和underflow。如果有version1和version3 这两种方法设计Stack,那么函数f()(用户的代码)也同样version1和version3。当一段日子过去了,我们准备再加入一个异常,比如midflow()(呵呵呵,我也想不出有什么类似的异常了)。这样的话,库设计者对用户说:“我们发现了midflow()异常,并加入库代码中,请您改写您的代码f()。”
这样我们的version1得修改成如下形式:
void  f()
{
    Stack
< string >  ss( 10 );
    
try {
     
// .
    }
    
catch (Stack < string > ::Overflow){
        cerr 
<<   " error: stack overflow "   <<  endl;
    }
    
catch (Stack < string > ::Underflow){
        cerr 
<<   " error: stack underflow "   <<  endl;
    }
    
catch (Stack < string > ::Midflow){     // 我们的找到所有扑捉stack异常的代码,并加入这两句。
          cerr  <<   " error: stack midflow "   <<  endl;
    }
}

而version3由于midflow()继承了stack_error。而其接口还是一样,客户代码就无需更改了。

 完毕。鞠躬。 请多多交流!

附:version3完整代码: 
 1  Version  3 :
 2  #include  < cstdlib >
 3  #include  < iostream >
 4 
 5  using   namespace  std;
 6 
 7  template < class  T > class  Stack{
 8      T *  v;
 9       int  max_size;
10       int  top;
11  public :
12       class  stack_error{
13       public :
14           virtual   void  error( void =   0 ;
15      };
16 
17       class  Underflow:  public  stack_error{       //
18       public :
19           void  error( void ){
20              cerr  <<   " stack Underflow "   <<  endl;
21          }    
22      };   
23       class  Overflow:  public  stack_error{        //  
24       public :
25           void  error( void ){
26              cerr  <<   " stack Overflow "   <<  endl;
27          } 
28      };   
29      Stack( int  s): max_size(s), top( 0 ){ v  =   new  T[max_size];}         //  construct function. determine the size   
30       ~ Stack(){}
31       void  push(T c){
32           if (top  ==  max_size)  throw  Overflow();
33          v[top ++ =  c;
34      }
35      T pop(){
36           if (top  ==   0 throw  Underflow();
37           return  v[ -- top];
38      }
39  }; 
40 
41  void  f()
42  {
43      Stack < string >  ss( 0 );
44       try {
45          ss.push( " Quiz " );
46           string  s  =  ss.pop();
47          ss.pop();
48      }
49       catch (Stack < string > ::stack_error &  e){
50          e.error();
51      }
52 
53  }
54 
55  int  main( int  argc,  char   * argv[])
56  {
57      f();
58      system( " PAUSE " );
59       return  EXIT_SUCCESS;
60  }

你可能感兴趣的:(异常处理)