📄 ch20.htm
字号:
19: 20: // friend function21: friend ostream& operator<< (ostream&, const Array&);22: 23: class xBoundary {}; // define the exception class24: 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) const71: {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;84: }85: 86: int main()87: {88: Array intArray(20);89: try90: {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 somewhatstripped-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 justa class like any other. This particular class is incredibly simple: It has no dataand 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 automaticallyassigns 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 twoclasses 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 preferentialaccess to the members of <TT>Array</TT>.</P><P>On lines 60-66 and 69-75, the offset operators are modified to examine the offsetrequested and, if it is out of range, to throw the <TT>xBoundary</TT> class as anexception. 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 thatyou provide a <TT>return</TT> statement to match the declaration (in this case, returningan integer reference), even though if an exception is thrown on line 65 the codewill never reach line 66. This is a compiler bug, proving only that even Microsoftfinds this stuff difficult and confusing!</P><P>On line 89, the keyword <TT>try</TT> begins a <TT>try</TT> block that ends online 96. Within that <TT>try</TT> block, 100 integers are added to the array thatwas declared on line 88.</P><P>On line 97, the <TT>catch</TT> block to catch <TT>xBoundary</TT> exceptions isdeclared.</P><P>In the driver program on lines 86-103, a <TT>try</TT> block is created in whicheach member of the array is initialized. When <TT>j</TT> (line 91) is incrementedto 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 exceptionis caught or handled by the <TT>catch</TT> on the same line, which prints an errormessage. Program flow drops through to the end of the <TT>catch</TT> block on line100.<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">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 theword <TT>catch</TT>, followed by an exception type in parentheses, followed by anopening brace, and ending with a closing brace. Example:</P><PRE><FONT COLOR="#0066FF">try{Function();};catch (OutOfMemory){// take action}</FONT></PRE><H3 ALIGN="CENTER"><A NAME="Heading11"></A><FONT COLOR="#000077">Using try Blocksand catch Blocks</FONT></H3><P>Figuring out where to put your <TT>try</TT> blocks is non-trivial: It is not alwaysobvious which actions might raise an exception. The next question is where to catchthe exception. It may be that you'll want to throw all memory exceptions where thememory 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 allocatememory or use resources. Other things to look for are out-of-bounds errors, illegalinput, 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 programinvokes 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 callstack. 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 stackis unwound, the destructors for local objects on the stack are invoked, and the objectsare 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 tobe handled by having that statement execute. If it doesn't match any, the unwindingof 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-waystreet. 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 afterthe <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 afterthe <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 afterthe <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 catchSpecification</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 conditionsin a <TT>switch</TT> statement. The equivalent to the <TT>default</TT> statementis the "catch everything" statement, indicated by <TT>catch(...)</TT>.Listing 20.2 illustrates multiple exception conditions.</P><P><A NAME="Heading14"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 20.2. Multipleexceptions.</B></FONT><PRE><FONT COLOR="#0066FF">0: #include <iostream.h>1: 2: const int DefaultSize = 10;3: 4: class Array5: {6: public:7: // constructors8: Array(int itsSize = DefaultSize);9: Array(const Array &rhs);10: ~Array() { delete [] pType;}11: 12: // operators13: Array& operator=(const Array&);14: int& operator[](int offSet);15: const int& operator[](int offSet) const;16: 17: // accessors18: int GetitsSize() const { return itsSize; }19: 20: // friend function21: friend ostream& operator<< (ostream&, const Array&);22: 23: // define the exception classes24: 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 MFC41: }42: 43: 44: const int& Array::operator[](int offSet) const45: {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 MFC52: }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: try78: {79: Array intArray(0);80: for (int j = 0; j< 100; j++)81: {82: intArray[j] = j;83: cout << "intArray[" << j << "] okay...\n";84: }85: }86: catch (Array::xBoundary)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -