📄 ch20.htm
字号:
105: {106: Array intArray(9);107: for (int j = 0; j< 100; j++)108: {109: intArray[j] = j;110: cout << "intArray[" << j << "] okay..." << endl;111: }112: }113: catch (Array::xBoundary)114: {115: cout << "Unable to process your input!\n";116: }117: catch (Array::xZero theException)118: {119: cout << "You asked for an Array of zero objects!" << endl;120: cout << "Received " << theException.GetSize() << endl;121: }122: catch (Array::xTooBig theException)123: {124: cout << "This Array is too big..." << endl;125: cout << "Received " << theException.GetSize() << endl;126: }127: catch (Array::xTooSmall theException)128: {129: cout << "This Array is too small..." << endl;130: cout << "Received " << theException.GetSize() << endl;131: }132: catch (...)133: {134: cout << "Something went wrong, but I've no idea what!\n";135: }136: cout << "Done.\n";137: return 0;<TT>138: }</TT></FONT><FONT COLOR="#0066FF">Output: This array is too small...Received 9Done.</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The declaration of <TT>xSize</TT>has been modified to include a member variable, <TT>itsSize</TT>, on line 32 anda member function, <TT>GetSize()</TT>, on line 30. Additionally, a constructor hasbeen added that takes an integer and initializes the member variable, as shown online 28.<BR>The derived classes declare a constructor that does nothing but initialize the baseclass. No other functions were declared, in part to save space in the listing.</P><P>The <TT>catch</TT> statements on lines 113 to 135 are modified to name the exceptionthey catch, <TT>theException</TT>, and to use this object to access the data storedin <TT>itsSize</TT>.<BLOCKQUOTE> <P><HR><FONT COLOR="#000077"><B>NOTE: </B></FONT>Keep in mind that if you are constructing an exception, it is because an exception has been raised: Something has gone wrong, and your exception should be careful not to kick off the same problem. Therefore, if you are creating an <TT>OutOfMemory</TT> exception, you probably don't want to allocate memory in its constructor. <HR></BLOCKQUOTE><P>It is tedious and error-prone to have each of these <TT>catch</TT> statementsindividually print the appropriate message. This job belongs to the object, whichknows what type of object it is and what value it received. Listing 20.5 takes amore object-oriented approach to this problem, using virtual functions so that eachexception "does the right thing."</P><P><A NAME="Heading21"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 20.5.Passingby reference and using virtual functions in exceptions.</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<< 22: (ostream&, const Array&);23: 24: // define the exception classes25: class xBoundary {};26: class xSize27: {28: public:29: xSize(int size):itsSize(size) {}30: ~xSize(){}31: virtual int GetSize() { return itsSize; }32: virtual void PrintError() 33: { 34: cout << "Size error. Received: ";35: cout << itsSize << endl; 36: }37: protected:38: int itsSize;39: };40: 41: class xTooBig : public xSize42: {43: public:44: xTooBig(int size):xSize(size){}45: virtual void PrintError() 46: { 47: cout << "Too big! Received: ";48: cout << xSize::itsSize << endl; 49: }50: };51: 52: class xTooSmall : public xSize53: {54: public:55: xTooSmall(int size):xSize(size){}56: virtual void PrintError() 57: { 58: cout << "Too small! Received: ";59: cout << xSize::itsSize << endl; 60: }61: };62: 63: class xZero : public xTooSmall64: {65: public:66: xZero(int size):xTooSmall(size){}67: virtual void PrintError() 68: { 69: cout << "Zero!!. Received: " ;70: cout << xSize::itsSize << endl; 71: }72: };73: 74: class xNegative : public xSize75: {76: public:77: xNegative(int size):xSize(size){}78: virtual void PrintError() 79: { 80: cout << "Negative! Received: ";81: cout << xSize::itsSize << endl; 82: }83: };84: 85: private:86: int *pType;87: int itsSize;88: };89: 90: Array::Array(int size):91: itsSize(size)92: {93: if (size == 0)94: throw xZero(size);95: if (size > 30000)96: throw xTooBig(size);97: if (size <1)98: throw xNegative(size);99: if (size < 10)100: throw xTooSmall(size);101: 102: pType = new int[size];103: for (int i = 0; i<size; i++)104: pType[i] = 0;105: }106: 107: int& Array::operator[] (int offSet)108: {109: int size = GetitsSize();110: if (offSet >= 0 && offSet < GetitsSize())111: return pType[offSet];112: throw xBoundary();113: return pType[0];114: }115: 116: const int& Array::operator[] (int offSet) const117: {118: int size = GetitsSize();119: if (offSet >= 0 && offSet < GetitsSize())120: return pType[offSet];121: throw xBoundary();122: return pType[0];123: }124: 125: int main()126: {127: 128: try129: {130: Array intArray(9);131: for (int j = 0; j< 100; j++)132: {133: intArray[j] = j;134: cout << "intArray[" << j << "] okay...\n";135: }136: }137: catch (Array::xBoundary)138: {139: cout << "Unable to process your input!\n";140: }141: catch (Array::xSize& theException)142: {143: theException.PrintError();144: }145: catch (...)146: {147: cout << "Something went wrong!\n";148: }149: cout << "Done.\n";150: return 0;<TT>151: }</TT></FONT><FONT COLOR="#0066FF">Output: Too small! Received: 9Done.</FONT></PRE><P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>Listing 20.5 declares a virtualmethod in the <TT>xSize</TT> class, <TT>PrintError()</TT>, that prints an error messageand the actual size of the class. This is overridden in each of the derived classes.<BR><BR>On line 141, the exception object is declared to be a reference. When <TT>PrintError()</TT>is called with a reference to an object, polymorphism causes the correct versionof <TT>PrintError()</TT> to be invoked. The code is cleaner, easier to understand,and easier to maintain.<H3 ALIGN="CENTER"><A NAME="Heading23"></A><FONT COLOR="#000077">Exceptions and Templates</FONT></H3><P>When creating exceptions to work with templates, you have a choice: you can createan exception for each instance of the template, or you can use exception classesdeclared outside the template declaration. Listing 20.6 illustrates both approaches.</P><P><A NAME="Heading24"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 20.6. Usingexceptions with templates.</B></FONT><PRE><FONT COLOR="#0066FF">0: #include <iostream.h>1: 2: const int DefaultSize = 10;3: class xBoundary {};4: 5: template <class T>6: class Array7: {8: public:9: // constructors10: Array(int itsSize = DefaultSize);11: Array(const Array &rhs);12: ~Array() { delete [] pType;}13: 14: // operators15: Array& operator=(const Array<T>&);16: T& operator[](int offSet);17: const T& operator[](int offSet) const;18: 19: // accessors20: int GetitsSize() const { return itsSize; }21: 22: // friend function23: friend ostream& operator<< (ostream&, const Array<T>&);24: 25: // define the exception classes26: 27: class xSize {};28: 29: private:30: int *pType;31: int itsSize;32: };33: 34: template <class T>35: Array<T>::Array(int size):36: itsSize(size)37: {38: if (size <10 || size > 30000)39: throw xSize();40: pType = new T[size];41: for (int i = 0; i<size; i++)42: pType[i] = 0;43: }44: 45: template <class T>46: Array<T>& Array<T>::operator=(const Array<T> &rhs)47: {48: if (this == &rhs)49: return *this;50: delete [] pType;51: itsSize = rhs.GetitsSize();52: pType = new T[itsSize];53: for (int i = 0; i<itsSize; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -