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