📄 ch20.htm
字号:
87: {
88: cout << "Unable to process your input!\n";
89: }
90: catch (Array::xTooBig)
91: {
92: cout << "This array is too big...\n";
93: }
94: catch (Array::xTooSmall)
95: {
96: cout << "This array is too small...\n";
97: }
98: catch (Array::xZero)
99: {
100: cout << "You asked for an array";
101: cout << " of zero objects!\n";
102: }
103: catch (...)
104: {
105: cout << "Something went wrong!\n";
106: }
107: cout << "Done.\n";
108: return 0;
<TT>109: }</TT></FONT>
<FONT COLOR="#0066FF">Output: You asked for an array of zero objects!
Done.</FONT></PRE>
<DL>
<DD><FONT COLOR="#0066FF"></FONT>
</DL>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Four new classes are created
in lines 24-27: <TT>xTooBig</TT>,<TT> xTooSmall</TT>,<TT> xZero</TT>, and <TT>xNegative</TT>.
In the constructor, on lines 55-70, the size passed to the constructor is examined.
If it's too big, too small, negative, or zero, an exception is thrown.</P>
<P>The <TT>try</TT> block is changed to include <TT>catch</TT> statements for each
condition other than negative, which is caught by the "catch everything"
statement <TT>catch(...)</TT>, shown on line 103.</P>
<P>Try this with a number of values for the size of the array. Then try putting in
<TT>-5</TT>. You might have expected <TT>xNegative</TT> to be called, but the order
of the tests in the constructor prevented this: <TT>size < 10</TT> was evaluated
before <TT>size < 1</TT>. To fix this, swap lines 60 and 61 with lines 64 and
65 and recompile.
<H4 ALIGN="CENTER"><A NAME="Heading15"></A><FONT COLOR="#000077">Exception Hierarchies</FONT></H4>
<P>Exceptions are classes, and as such they can be derived from. It may be advantageous
to create a class <TT>xSize</TT>, and to derive from it <TT>xZero</TT>,<TT> xTooSmall</TT>,<TT>
xTooBig</TT>, and <TT>xNegative</TT>. Thus, some functions might just catch <TT>xSize</TT>
errors, while other functions might catch the specific type of <TT>xSize</TT> error.
Listing 20.3 illustrates this idea.</P>
<P><A NAME="Heading16"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 20.3. Class
hierarchies and exceptions.</B></FONT>
<PRE><FONT COLOR="#0066FF">0: #include <iostream.h>
1:
2: const int DefaultSize = 10;
3:
4: class Array
5: {
6: public:
7: // constructors
8: Array(int itsSize = DefaultSize);
9: Array(const Array &rhs);
10: ~Array() { delete [] pType;}
11:
12: // operators
13: Array& operator=(const Array&);
14: int& operator[](int offSet);
15: const int& operator[](int offSet) const;
16:
17: // accessors
18: int GetitsSize() const { return itsSize; }
19:
20: // friend function
21: friend ostream& operator<< (ostream&, const Array&);
22:
23: // define the exception classes
24: class xBoundary {};
25: class xSize {};
26: class xTooBig : public xSize {};
27: class xTooSmall : public xSize {};
28: class xZero : public xTooSmall {};
29: class xNegative : public xSize {};
30: private:
31: int *pType;
32: int itsSize;
33: };
34:
35:
36: Array::Array(int size):
37: itsSize(size)
38: {
39: if (size == 0)
40: throw xZero();
41: if (size > 30000)
42: throw xTooBig();
43: if (size <1)
44: throw xNegative();
45: if (size < 10)
46: throw xTooSmall();
47:
48: pType = new int[size];
49: for (int i = 0; i<size; i++)
50: pType[i] = 0;
51: }
52:
53: int& Array::operator[](int offSet)
54: {
55: int size = GetitsSize();
56: if (offSet >= 0 && offSet < GetitsSize())
57: return pType[offSet];
58: throw xBoundary();
59: return pType[0]; // appease MFC
60: }
61:
62:
63: const int& Array::operator[](int offSet) const
64: {
65: int mysize = GetitsSize();
66: if (offSet >= 0 && offSet < GetitsSize())
67: return pType[offSet];
68: throw xBoundary();
69: return pType[0];
70: return pType[0]; // appease MFC
71: }
72:
73: int main()
74: {
75:
76: try
77: {
78: Array intArray(5);
79: for (int j = 0; j< 100; j++)
80: {
81: intArray[j] = j;
82: cout << "intArray[" << j << "] okay...\n";
83: }
84: }
85: catch (Array::xBoundary)
86: {
87: cout << "Unable to process your input!\n";
88: }
89: catch (Array::xTooBig)
90: {
91: cout << "This array is too big...\n";
92: }
93:
94: catch (Array::xZero)
95: {
96: cout << "You asked for an array";
97: cout << " of zero objects!\n";
98: }
99:
100: catch (Array::xTooSmall)
101: {
102: cout << "This array is too small...\n";
103: }
104:
105: catch (...)
106: {
107: cout << "Something went wrong!\n";
108: }
109: cout << "Done.\n";
110: return 0
<TT>111: }</TT>
Output: This array is too small...
Done.
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The significant change is
on lines 26-29, where the class hierarchy is established. Classes <TT>xTooBig</TT>,<TT>
xTooSmall</TT>, and <TT>xNegative</TT> are derived from <TT>xSize</TT>, and <TT>xZero</TT>
is derived from <TT>xTooSmall</TT>.<BR>
<BR>
The <TT>Array</TT> is created with size zero, but what's this? The wrong exception
appears to be caught! Examine the <TT>catch</TT> block carefully, however, and you
will find that it looks for an exception of type <TT>xTooSmall</TT> before it looks
for an exception of type <TT>xZero</TT>. Because an <TT>xZero</TT> object is thrown
and an <TT>xZero</TT> object is an <TT>xTooSmall</TT> object, it is caught by the
handler for <TT>xTooSmall</TT>. Once handled, the exception is not passed on to the
other handlers, so the handler for <TT>xZero</TT> is never called.</P>
<P>The solution to this problem is to carefully order the handlers so that the most
specific handlers come first and the less specific handlers come later. In this particular
example, switching the placement of the two handlers <TT>xZero</TT> and <TT>xTooSmall</TT>
will fix the problem.
<H3 ALIGN="CENTER"><A NAME="Heading18"></A><FONT COLOR="#000077">Data in Exceptions
and Naming Exception Objects</FONT></H3>
<P>Often you will want to know more than just what type of exception was thrown so
you can respond properly to the error. Exception classes are like any other class.
You are free to provide data, initialize that data in the constructor, and read that
data at any time. Listing 20.4 illustrates how to do this.</P>
<P><A NAME="Heading19"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 20.4. Getting
data out of an exception object.</B></FONT>
<PRE><FONT COLOR="#0066FF">0: #include <iostream.h>
1:
2: const int DefaultSize = 10;
3:
4: class Array
5: {
6: public:
7: // constructors
8: Array(int itsSize = DefaultSize);
9: Array(const Array &rhs);
10: ~Array() { delete [] pType;}
11:
12: // operators
13: Array& operator=(const Array&);
14: int& operator[](int offSet);
15: const int& operator[](int offSet) const;
16:
17: // accessors
18: int GetitsSize() const { return itsSize; }
19:
20: // friend function
21: friend ostream& operator<< (ostream&, const Array&);
22:
23: // define the exception classes
24: class xBoundary {};
25: class xSize
26: {
27: public:
28: xSize(int size):itsSize(size) {}
29: ~xSize(){}
30: int GetSize() { return itsSize; }
31: private:
32: int itsSize;
33: };
34:
35: class xTooBig : public xSize
36: {
37: public:
38: xTooBig(int size):xSize(size){}
39: };
40:
41: class xTooSmall : public xSize
42: {
43: public:
44: xTooSmall(int size):xSize(size){}
45: };
46:
47: class xZero : public xTooSmall
48: {
49: public:
50: xZero(int size):xTooSmall(size){}
51: };
52:
53: class xNegative : public xSize
54: {
55: public:
56: xNegative(int size):xSize(size){}
57: };
58:
59: private:
60: int *pType;
61: int itsSize;
62: };
63:
64:
65: Array::Array(int size):
66: itsSize(size)
67: {
68: if (size == 0)
69: throw xZero(size);
70: if (size > 30000)
71: throw xTooBig(size);
72: if (size <1)
73: throw xNegative(size);
74: if (size < 10)
75: throw xTooSmall(size);
76:
77: pType = new int[size];
78: for (int i = 0; i<size; i++)
79: pType[i] = 0;
80: }
81:
82:
83: int& Array::operator[] (int offSet)
84: {
85: int size = GetitsSize();
86: if (offSet >= 0 && offSet < GetitsSize())
87: return pType[offSet];
88: throw xBoundary();
89: return pType[0];
90: }
91:
92: const int& Array::operator[] (int offSet) const
93: {
94: int size = GetitsSize();
95: if (offSet >= 0 && offSet < GetitsSize())
96: return pType[offSet];
97: throw xBoundary();
98: return pType[0];
99: }
100:
101: int main()
102: {
103:
104: try
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -