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