0: #include <iostream.h> 1: 2: const int DefaultSize = 10; 3: 4: class Array 5: { 6: public: 7:...
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<<
22: (ostream&, const Array&);
23:
24: // define the exception classes
25: class xBoundary {};
26: class xSize
27: {
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 xSize
42: {
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 xSize
53: {
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 xTooSmall
64: {
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 xSize
75: {
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) const
117: {
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: try
129: {
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;
151: }
Output: Too small! Received: 9
Done.
Analysis: Listing 20.5 declares a virtual method in the xSize class, PrintError(), that prints an error message and the actual size of the class. This is overridden in each of the derived classes.
On line 141, the exception object is declared to be a reference. When PrintError() is called with a reference to an object, polymorphism causes the correct version of PrintError() to be invoked. The code is cleaner, easier to understand, and easier to maintain.