It is possible for more than one condition to cause an exception. In this case, the catch statements can be lined up one after another, m...
It is possible for more than one condition to cause an exception. In this case, the catch statements can be lined up one after another, much like the conditions in a switch statement. The equivalent to the default statement is the "catch everything" statement, indicated by catch(...). Listing 20.2 illustrates multiple exception conditions.
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";
84: }
85: }
86: catch (Array::xBoundary)
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;
109: }
Output: You asked for an array of zero objects!
Done.
Analysis: Four new classes are created in lines 24-27: xTooBig, xTooSmall, xZero, and xNegative. 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.
The try block is changed to include catch statements for each condition other than negative, which is caught by the "catch everything" statement catch(...), shown on line 103.
Try this with a number of values for the size of the array. Then try putting in -5. You might have expected xNegative to be called, but the order of the tests in the constructor prevented this: size < 10 was evaluated before size < 1. To fix this, swap lines 60 and 61 with lines 64 and 65 and recompile.