Latest

recent

Data in Exceptions and Naming Exception Objects in C++


Often you will want to know more than just what type of exception was thrown so you can respond properly to the error. Exception classes are like any other class. You are free to provide data, initialize that data in the constructor, and read that data at any time. Listing 20.4 illustrates how to do this.

Listing 20.4. Getting data out of an exception object.

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 xSize
26: {
27: public:
28: xSize(int size):itsSize(size) {}
29: ~xSize(){}
30: int GetSize() { return itsSize; }
31: private:
32: int itsSize;
33: };
34:
35: class xTooBig : public xSize
36: {
37: public:
38: xTooBig(int size):xSize(size){}
39: };
40:
41: class xTooSmall : public xSize
42: {
43: public:
44: xTooSmall(int size):xSize(size){}
45: };
46:
47: class xZero : public xTooSmall
48: {
49: public:
50: xZero(int size):xTooSmall(size){}
51: };
52:
53: class xNegative : public xSize
54: {
55: public:
56: xNegative(int size):xSize(size){}
57: };
58:
59: private:
60: int *pType;
61: int itsSize;
62: };
63:
64:
65: Array::Array(int size):
66: itsSize(size)
67: {
68: if (size == 0)
69: throw xZero(size);
70: if (size > 30000)
71: throw xTooBig(size);
72: if (size <1)
73: throw xNegative(size);
74: if (size < 10)
75: throw xTooSmall(size);
76:
77: pType = new int[size];
78: for (int i = 0; i<size; i++)
79: pType[i] = 0;
80: }
81:
82:
83: int& Array::operator[] (int offSet)
84: {
85: int size = GetitsSize();
86: if (offSet >= 0 && offSet < GetitsSize())
87: return pType[offSet];
88: throw xBoundary();
89: return pType[0];
90: }
91:
92: const int& Array::operator[] (int offSet) const
93: {
94: int size = GetitsSize();
95: if (offSet >= 0 && offSet < GetitsSize())
96: return pType[offSet];
97: throw xBoundary();
98: return pType[0];
99: }
100:
101: int main()
102: {
103:
104: try
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;
138: }




Output: This array is too small...
Received 9
Done.
 
Analysis: The declaration of xSize has been modified to include a member variable, itsSize, on line 32 and a member function, GetSize(), on line 30. Additionally, a constructor has been added that takes an integer and initializes the member variable, as shown on line 28.
The derived classes declare a constructor that does nothing but initialize the base class. No other functions were declared, in part to save space in the listing.
The catch statements on lines 113 to 135 are modified to name the exception they catch, theException, and to use this object to access the data stored in itsSize.

NOTE: 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 OutOfMemory exception, you probably don't want to allocate memory in its constructor.

It is tedious and error-prone to have each of these catch statements individually print the appropriate message. This job belongs to the object, which knows what type of object it is and what value it received. Listing 20.5 takes a more object-oriented approach to this problem, using virtual functions so that each exception "does the right thing."
Data in Exceptions and Naming Exception Objects in C++ Reviewed by 1000sourcecodes on 22:33 Rating: 5
Powered by Blogger.