1
  2  A kivételeket specializálhatjuk, vagy generalizálhatjuk:
  3  objektum-orientáltság: alkalmazzunk az öröklődést
  4
  5
  6
  7  // öröklődési hierarchia a kivételek között
  8  class Base { ... };
  9  class Der1 : public Base { ... };
 10  class Der2 : public Base { ... };
 11  class Der3 : public Base { ... };
 12
 13
 14  void f()
 15  {
 16      // ...
 17      throw Der2();   // mindig a legspecifikusabb osztályt dobjuk
 18  }
 19
 20
 21  try
 22  {
 23      f();
 24      ...
 25  }
 26  catch( Der1 d1 ) { ... }
 27  catch( Der2 d2 ) { ... }
 28  catch( Der3 d3 ) { ... }
 29  catch( Base b )  { ... }  // mindig a bázis handler legyen az utolsó
 30
 31
 32
 33
 34  // egy egyszerű példa (lám-lám, mire jó a többszörös öröklődés):
 35
 36  class net_error { ... };
 37  class file_error { ... };
 38
 39  class nfs_error : public net_error, public file_error { ... };
 40
 41
 42  void f()
 43  {
 44      //...
 45      throw nfs_error();
 46  }
 47
 48
 49  try
 50  {
 51      ...
 52  }
 53  catch( nfs_error nfs ) { /* nfs hibaként kezeljük le */ }
 54  catch( file_error fe ) { /* fájlhibaként kezeljük le */ }
 55  catch( net_error ne )  { /* hálózati hibaként kezeljük le*/ }
 56
 57
 58
 59
 60  A szabványos könyvtár kivételei:            // ebben a header-ben:
 61
 62
 63  class exception {};                         // <exception>
 64  class bad_alloc  : public exception {};     // <new> new dobja
 65  class bad_cast   : public exception {};     // dynamic_cast dobja
 66  class bad_typeid : public exception {};     // typeid(0)
 67  class ios_base::failure : public exception {};  // <ios>
 68  class bad_exception : public exception {};  // lásd lejjebb
 69
 70  class runtime_error : public exception {};  // math. függvények
 71
 72  class range_error     : public runtime_error {};
 73  class overflow_error  : public runtime_error {};
 74  class underflow_error : public runtime_error {};
 75
 76  class logic_error : public exception {};
 77
 78  class domain_error : public logic_error {}; // domain 
 79  class invalid_argument : public logic_error {}; // bitset char!=0 vagy 1
 80  class length_error : public logic_error {}; // std::string length() 
 81  class out_of_range : public logic_error {}; // indexhiba pl. std::string
 82
 83
 84  namespace std
 85  {
 86      class exception
 87      {
 88      public:
 89          virtual const char *what() const throw();
 90          ...
 91      };
 92  }
 93
 94
 95
 96
 97  // másik példa:
 98
 99
100  #ifndef MATRIX_H
101  #define MATRIX_H
102
103  #include <string>
104  #include <sstream>
105  #include <stdexcept>
106
107  // a mátrix-al kapcsolatos hibák bázisosztálya
108  struct matrixError
109  {
110      matrixError( std::string r) : reason(r) { }
111      const std::string reason;   // a hiba oka szövegesen
112  };
113
114  // mások mellett: hibás indexelésből származó hiba
115  // az std konvenciói miatt örököl std::out_of_range-ből
116  struct indexError : public matrixError, public std::out_of_range
117  {
118      indexError( int i, const char *r="Bad index") :
119                    matrixError(r), out_of_range(r), index(i) { }
120      const char *what() const throw()
121      {
122          std::ostringstream os;
123          os << std::out_of_range::what();
124          os << ", index = " << index;
125          return os.str().c_str();
126     }
127     int index;   // ez a hibás index
128  };
129
130  // specializálja a hibát: hibás sorindex
131  struct rowIndexError : public indexError
132  {
133      rowIndexError(int i) : indexError( i, "Bad row index") { }
134  };
135
136  // specializálja a hibát: hibás oszlopindex
137  struct colIndexError : public indexError
138  {
139      colIndexError(int i) : indexError( i, "Bad col index") { }
140  };
141
142  template <class T>
143  class matrix
144  {
145  public:
146         // a konstruktorok gyakran kivételt dobnak:
147         matrix( int i, int j ) throw(matrixError);
148         matrix( const matrix &other) throw(matrixError);
149         // destruktor sohase dobjon kivételt!
150         ~matrix() throw();
151      matrix operator=( const matrix &other);
152
153      int rows() const { return x; }
154      int cols() const { return y; }
155
156      // konvenció: at() kivételt dob
157      T& at( int i, int j) throw(indexError);
158      T  at( int i, int j) const throw(indexError);
159      // konvenció: operator() nem dob kivételt
160      T& operator()( int i, int j);
161      T  operator()( int i, int j) const;
162
163      matrix operator+=( const matrix &other);
164
165  private:
166      int  x;
167      int  y;
168      T   *v;
169      void copy( const matrix &other);
170      void check( int i, int j) const throw(indexError);
171  };
172
173  // ellenőrizzük az indexhatárokat
174  void matrix<T>::check( int i, int j) const throw( indexError )
175  {
176      if ( i  < 0  ||  i >= x )
177          throw rowIndexError(i);
178      if ( j  < 0  ||  j >= y )
179          throw colIndexError(j);
180  }
181  template <class T>
182  T& matrix<T>::at( int i, int j) throw(indexError)
183  {
184      check(i,j);
185      return operator()(i,j);
186  }
187  template <class T>
188  T matrix<T>::at( int i, int j) const throw( indexError)
189  {
190      check(i,j);
191      return operator()(i,j);
192  }
193
194  #endif /* MATRIX_H */
195
196
197
198  #include <iostream>
199  #include "matrix.h"
200  #include "date.h"
201
202  using namespace std;
203
204  int main()
205  {
206      date          d(2001,1,1);
207      matrix<date>  md(52,7);
208
209      for ( int i = 0; i < md.rows(); ++i )
210          for ( int j = 0; j < md.cols(); ++j )
211              md( i, j ) = d++;
212
213      int week, day;
214      while ( cin >> week >> day )
215      try
216      {
217          cout << md.at( --week, --day ) << endl;
218      }
219      catch( rowIndexError e )
220      {
221          cerr << e.what() << ", row = " << e.row << endl;
222      }
223      catch( out_of_range e )
224      {
225          cerr << e.what() << endl;
226      }
227      catch(...)
228      {
229          cerr << "some error, try again" << endl;
230      }
231      return 0;
232  }
233
234