?? 020.htm
字號(hào):
19:
20: // friend function
21: friend ostream& operator<< (ostream&, const Array&);
22:
23: class xBoundary {}; // define the exception class
24: private:
25: int *pType;
26: int itsSize;
27: };
28:
29:
30: Array::Array(int size):
31: itsSize(size)
32: {
33: pType = new int[size];
34: for (int i = 0; i<size; i++)
35: pType[i] = 0;
36: }
37:
38:
39: Array& Array::operator=(const Array &rhs)
40: {
41: if (this == &rhs)
42: return *this;
43: delete [] pType;
44: itsSize = rhs.GetitsSize();
45: pType = new int[itsSize];
46: for (int i = 0; i<itsSize; i++)
47: pType[i] = rhs[i];
48: return *this;
49: }
50:
51: Array::Array(const Array &rhs)
52: {
53: itsSize = rhs.GetitsSize();
54: pType = new int[itsSize];
55: for (int i = 0; i<itsSize; i++)
56: pType[i] = rhs[i];
57: }
58:
59:
60: int& Array::operator[](int offSet)
61: {
62: int size = GetitsSize();
63: if (offSet >= 0 && offSet < GetitsSize())
64: return pType[offSet];
65: throw xBoundary();
66: return pType[0]; // appease MSC
67: }
68:
69:
70: const int& Array::operator[](int offSet) const
71: {
72: int mysize = GetitsSize();
73: if (offSet >= 0 && offSet < GetitsSize())
74: return pType[offSet];
75: throw xBoundary();
76: return pType[0]; // appease MSC
77: }
78:
79: ostream& operator<< (ostream& output, const Array& theArray)
80: {
81: for (int i = 0; i<theArray.GetitsSize(); i++)
82: output << "[" << i << "] " << theArray[i] << endl;
83: return output;
100: }
85:
86: int main()
87: {
88: Array intArray(20);
89: try
90: {
91: for (int j = 0; j< 100; j++)
92: {
93: intArray[j] = j;
94: cout << "intArray[" << j << "] okay..." << endl;
95: }
96: }
97: catch (Array::xBoundary)
98: {
99: cout << "Unable to process your input!\n";
100: }
101: cout << "Done.\n";
102: return 0;
<TT>103: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: intArray[0] okay...
intArray[1] okay...
intArray[2] okay...
intArray[3] okay...
intArray[4] okay...
intArray[5] okay...
intArray[6] okay...
intArray[7] okay...
intArray[8] okay...
intArray[9] okay...
intArray[10] okay...
intArray[11] okay...
intArray[12] okay...
intArray[13] okay...
intArray[14] okay...
intArray[15] okay...
intArray[16] okay...
intArray[17] okay...
intArray[18] okay...
intArray[19] okay...
Unable to process your input!
Done.
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Listing 20.1 presents a somewhat
stripped-down <TT>Array</TT> class, based on the template developed on Day 19, "Templates."
On line 23, a new class is contained within the declaration of the boundary.<BR>
<BR>
This new class is not in any way distinguished as an exception class. It is just
a class like any other. This particular class is incredibly simple: It has no data
and no methods. Nonetheless, it is a valid class in every way.</P>
<P>In fact, it is incorrect to say it has no methods, because the compiler automatically
assigns it a default constructor, destructor, copy constructor, and the copy operator
(operator equals); so it actually has four class functions, but no data.</P>
<P>Note that declaring it from within <TT>Array</TT> serves only to couple the two
classes together. As discussed on Day 15, "Advanced Inheritance," <TT>Array</TT>
has no special access to <TT>xBoundary</TT>, nor does <TT>xBoundary</TT> have preferential
access to the members of <TT>Array</TT>.</P>
<P>On lines 60-66 and 69-75, the offset operators are modified to examine the offset
requested and, if it is out of range, to throw the <TT>xBoundary</TT> class as an
exception. The parentheses are required to distinguish between this call to the <TT>xBoundary</TT>
constructor and the use of an enumerated constant. Note that Microsoft requires that
you provide a <TT>return</TT> statement to match the declaration (in this case, returning
an integer reference), even though if an exception is thrown on line 65 the code
will never reach line 66. This is a compiler bug, proving only that even Microsoft
finds this stuff difficult and confusing!</P>
<P>On line 89, the keyword <TT>try</TT> begins a <TT>try</TT> block that ends on
line 96. Within that <TT>try</TT> block, 100 integers are added to the array that
was declared on line 88.</P>
<P>On line 97, the <TT>catch</TT> block to catch <TT>xBoundary</TT> exceptions is
declared.</P>
<P>In the driver program on lines 86-103, a <TT>try</TT> block is created in which
each member of the array is initialized. When <TT>j</TT> (line 91) is incremented
to 20, the member at offset 20 is accessed. This causes the test on line 63 to fail,
and <TT>operator[]</TT> raises an <TT>xBoundary</TT> exception on line 65.</P>
<P>Program control switches to the <TT>catch</TT> block on line 97, and the exception
is caught or handled by the <TT>catch</TT> on the same line, which prints an error
message. Program flow drops through to the end of the <TT>catch</TT> block on line
100.
<H3 ALIGN="CENTER"><A NAME="Heading9"></A><FONT COLOR="#000077">try Blocks</FONT></H3>
<P>A <TT>try</TT> block is a set of statements that begins with the word <TT>try</TT>,
is followed by an opening brace, and ends with a closing brace. Example:</P>
<PRE><FONT COLOR="#0066FF" font style="font-size:10pt">try
{
Function();
};
</FONT></PRE>
<H3 ALIGN="CENTER"><A NAME="Heading10"></A><FONT COLOR="#000077">catch Blocks</FONT></H3>
<P>A <TT>catch</TT> block is a series of statements, each of which begins with the
word <TT>catch</TT>, followed by an exception type in parentheses, followed by an
opening brace, and ending with a closing brace. Example:</P>
<PRE><FONT COLOR="#0066FF" font style="font-size:10pt">try
{
Function();
};
catch (OutOfMemory)
{
// take action
}
</FONT></PRE>
<H3 ALIGN="CENTER"><A NAME="Heading11"></A><FONT COLOR="#000077">Using try Blocks
and catch Blocks</FONT></H3>
<P>Figuring out where to put your <TT>try</TT> blocks is non-trivial: It is not always
obvious which actions might raise an exception. The next question is where to catch
the exception. It may be that you'll want to throw all memory exceptions where the
memory is allocated, but you'll want to catch the exceptions high in the program,
where you deal with the user interface.</P>
<P>When trying to determine <TT>try</TT> block locations, look to where you allocate
memory or use resources. Other things to look for are out-of-bounds errors, illegal
input, and so forth.
<H4 ALIGN="CENTER"><A NAME="Heading12"></A><FONT COLOR="#000077">Catching Exceptions</FONT></H4>
<P>Here's how it works: when an exception is thrown, the call stack is examined.
The call stack is the list of function calls created when one part of the program
invokes another function.</P>
<P>The call stack tracks the execution path. If <TT>main()</TT> calls the function
<TT>Animal::GetFavoriteFood()</TT>, and <TT>GetFavoriteFood()</TT> calls <TT>Animal::LookupPreferences()</TT>,
which in turn calls <TT>fstream::operator>>()</TT>, all these are on the call
stack. A recursive function might be on the call stack many times.</P>
<P>The exception is passed up the call stack to each enclosing block. As the stack
is unwound, the destructors for local objects on the stack are invoked, and the objects
are destroyed.</P>
<P>After each <TT>try</TT> block there is one or more <TT>catch</TT> statements.
If the exception matches one of the <TT>catch</TT> statements, it is considered to
be handled by having that statement execute. If it doesn't match any, the unwinding
of the stack continues.</P>
<P>If the exception reaches all the way to the beginning of the program (<TT>main()</TT>)
and is still not caught, a built-in handler is called that terminates the program.</P>
<P>It is important to note that the exception unwinding of the stack is a one-way
street. As it progresses, the stack is unwound and objects on the stack are destroyed.
There is no going back: Once the exception is handled, the program continues after
the <TT>try</TT> block of the <TT>catch</TT> statement that handled the exception.</P>
<P>Thus, in Listing 20.1, execution will continue on line 101, the first line after
the <TT>try</TT> block of the <TT>catch</TT> statement that handled the <TT>xBoundary</TT>
exception. Remember that when an exception is raised, program flow continues after
the <TT>catch</TT> block, not after the point where the exception was thrown.
<H4 ALIGN="CENTER"><A NAME="Heading13"></A><FONT COLOR="#000077">More Than One catch
Specification</FONT></H4>
<P>It is possible for more than one condition to cause an exception. In this case,
the <TT>catch</TT> statements can be lined up one after another, much like the conditions
in a <TT>switch</TT> statement. The equivalent to the <TT>default</TT> statement
is the "catch everything" statement, indicated by <TT>catch(...)</TT>.
Listing 20.2 illustrates multiple exception conditions.</P>
<BR>
<P><A NAME="Heading14"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 20.2. Multiple
exceptions.</B></FONT>
<PRE><FONT COLOR="#0066FF" font style="font-size:10pt">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 xTooBig {};
26: class xTooSmall{};
27: class xZero {};
28: class xNegative {};
29: private:
30: int *pType;
31: int itsSize;
32: };
33:
34: int& Array::operator[](int offSet)
35: {
36: int size = GetitsSize();
37: if (offSet >= 0 && offSet < GetitsSize())
38: return pType[offSet];
39: throw xBoundary();
40: return pType[0]; // appease MFC
41: }
42:
43:
44: const int& Array::operator[](int offSet) const
45: {
46: int mysize = GetitsSize();
47: if (offSet >= 0 && offSet < GetitsSize())
48: return pType[offSet];
49: throw xBoundary();
50: return pType[0];
51: return pType[0]; // appease MFC
52: }
53:
54:
55: Array::Array(int size):
56: itsSize(size)
57: {
58: if (size == 0)
59: throw xZero();
60: if (size < 10)
61: throw xTooSmall();
62: if (size > 30000)
63: throw xTooBig();
64: if (size < 1)
65: throw xNegative();
66:
67: pType = new int[size];
68: for (int i = 0; i<size; i++)
69: pType[i] = 0;
70: }
71:
72:
73:
74: int main()
75: {
76:
77: try
78: {
79: Array intArray(0);
80: for (int j = 0; j< 100; j++)
81: {
82: intArray[j] = j;
83: cout << "intArray[" << j << "] okay...\n";
100: }
85: }
86: catch (Array::xBoundary)
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -