䊐 Exception Class MembersWhen an exception is thrown, the exception object type determines which exception handler will be executed.. When an exception is thrown, Example: throw MathErro
Trang 1䊐 Exception Class Members
When an exception is thrown, the exception object type determines which exception handler will be executed For this reason, an exception class does not need to have any members
However, an exception class can contain data members and methods—just like any other class This makes sense, as locally defined non-static objects are destroyed when an exception has been thrown and the stack is unwound Thus, the exception handler can
no longer access the previously existing objects
You can use the data members of error classes to rescue data threatened by an error condition For example, you can store data important for exception handling in an exception object
The exception class MathErroris defined opposite The calc()function throws an exception when a number input by a user is negative or 0 When an exception is thrown,
Example: throw MathError("Division by 0!");
the error message is stored in the exception object The exception handler can then use thegetMessage()method to evaluate the message
䊐 Exception Hierarchies
New exception classes can be derived from existing exception classes A base class will normally represent a general error type and specific errors will be represented by derived classes
Thus, the exception class MathErrorcould be defined to represent general errors in mathematical computations, but it would make sense to define derived exception classes for special cases, such as “Division by 0” or “Arithmetic overflow.” You could call these classesDivisionByZeroandOverflowError, for example
Be aware of the following rules for exception handlers in this context:
■ given that T is a derived exception class, special errors of this type are handled by the exception handler
■ if T is a base class, the handler will also catch the exception objects thrown by derived classes, thus providing similar handling for generic and specific errors
Trang 2620 C H A P T E R 2 8 E X C E P T I O N H A N D L I N G
invalid_argument out_of_range
length_error domain_error
Invalid argument Argument value not in its expected range Length exceeds maximum capacity Domain error reported by the implementation
range_error
underflow_error overflow_error
Range error in internal computation Arithmetic underflow error
Arithmetic overflow error
// Subscript operator of class FloatArr throws // exceptions with type of standard class out_of_range: //
-#include <stdexcept>
#include <iostream>
using namespace std;
double& FloatArr::operator[](int i) throw(out_of_range)
{ if( i < 0 || i >= anz )
throw out_of_range("Invalid index!");
else return arrPtr[i];
} // - Test Program -int main()
{
try {
// Uses arrays of type FloatArr
} catch(out_of_range& err) {
cerr << err.what() << endl;
}
// The program continues here
}
Exception classes derived from logic_error
Exception classes derived from runtime_error
Using standard exception classes
Trang 3䊐 Hierarchy of Standard Exception Classes
The C++ standard library contains various exception classes, which are used in the string and container libraries, for example However, the standard exception classes can be used just like exception classes of your own Their definitions are to be found in the header file stdexcept
The standard exception classes are organized in a hierarchy, the common base class being the exceptionclass In addition to a default constructor, a copy constructor, and
an assignment, this class contains a virtual public method,what(), which returns a message on the error cause as a C string
䊐 Representing Logic Errors and Runtime Errors
The following exception classes are derived from the exceptionclass:
logic_error used to represent logic errors, caused by anomalies in the program’s
logic These errors can be avoided
runtime_error used to represent runtime errors, such as under- or overflows
occur-ring in internal computations These errors are unpredictable The opposite page contains on overview of the exception classes derived from the
logic_error andruntime_error classes For example, the method at() in the
stringclass throws an out_of_rangetype exception when an invalid string position
is passed to it If a string cannot be displayed because of its exceptional length, an excep-tion of the invalid_argumenttype is thrown
An exception of the overflow_errororunderflow_errortype is thrown if the value to be displayed is too large or too small for the type in use The range_error
class shows range errors, which can occur during internal computations
A constructor with a string as a parameter is defined in every class derived from
exception This means you can initialize exceptions of these types with error messages Thewhat()method returns this error message as a C string
Trang 4622 C H A P T E R 2 8 E X C E P T I O N H A N D L I N G
Error in reading:
Invalid index:
Error in writing:
Invalid index:
Exercise 1: Error messages of the exception handler
The first exception handler’s message:
The second exception handler’s message:
Trang 5Exercise 1
TheFloatArrclass needs exception handling for cases where an invalid index is stated when accessing an array member.
■ Define the exception class BadIndexfor this purpose and store the class
in the header file “floatArr.h”.The exception class must contain a data member to store the invalid index.The constructor expects an index that it will copy to the data member.The constaccess method
getBadIndex()returns the data member.
Both subscript operators should be able to throw BadIndextype excep-tions.Add an exception specification to the declaration of the subscript operators.
The methods that expect the position as an argument, such as insert()
andremove(), should also throw exceptions.Add appropriate exception specifications to the definitions and change the return types from boolto
void.
■ Change the definitions of the methods and operator functions to allow a
BadIndextype exception to be thrown when the index passed to the function is outside the valid range.
■ Write a mainfunction where a constant vector is created and initialized with fixed values Exception handling is required for the following scenar-ios.The array elements are displayed and an index is read until an invalid index value is input.The catchhandler should output the information shown opposite for each invalid index.
Then create a non-constant array.Add further exception handling to be performed Elements are appended or inserted within a tryblock.
Include an invalid element access attempt, which causes the catch han-dler to output the information shown opposite.Then finally output the array elements outside the tryandcatchblocks.
Trang 6624 C H A P T E R 2 8 E X C E P T I O N H A N D L I N G
Exercises
For Exercise 2: Error messages of the exception handlers
Messages of the exception handlers for an exception object of type DivisionByZero:
Error in initializing:
The denominator is 0!
Error in division:
No division by zero!
Error: Denominator is 0!
New denominator != 0:
Trang 7Exercise 2
Implement exception handling for the Fractionclass, which is used to
represent fractions (see Exercise 2, Chapter 19) Dividing by 0 throws an
exception that affects the constructor for the Fractionclass and the operator functions/and>>.
■ Define the exception class DivError, which has no data members, within theFractionclass.The exception class is of the following type
Fraction::DivError
Add an appropriate exception specification to the declarations of the constructor and the operator functions /and>>.
■ Change the definition of the constructor in the Fractionclass If the value of the denominator is 0, a DivisionByZerotype exception should
be thrown.
■ Similarly modify the operator functions.
■ Now write a mainfunction to test the various exceptions.You will need
to arrange three different tryandcatchblocks sequentially.
The first try/catchblock tests the constructor Create several fractions, including some with a numerator value of 0 and one with 0 as its
denominator.The exception handler should issue the error message shown opposite.
The second try/catchblock tests divisions Use a statement to attempt
to divide by 0.The corresponding exception handler should send the second error message shown opposite to your standard output.
The third try/catchblock reads numerators and denominators of fractions in dialog If the value of the denominator is 0, the denominator is read again If the value is still 0, the third error message as shown
opposite is output and the program terminates.
Trang 8626 C H A P T E R 2 8 E X C E P T I O N H A N D L I N G
Exercise 1
// -// floatArr.h : Represents dynamic float arrays
// Methods throw exceptions for an invalid index
//
-#ifndef _FLOATARR_
#define _FLOATARR_
#include <iostream>
using namespace std;
class BadIndex
{ private:
int index;
public:
BadIndex(int i){index = i;}
int getBadIndex() const {return index;}
};
class FloatArr
{ private:
float* arrPtr; // Dynamic member int max; // Maximum number without
// reallocating more memory
int cnt; // Current number of elements
void expand( int newSize); // Function to help
// enlarge the array public:
FloatArr( int n = 256 ); // Constructors FloatArr( int n, float val);
FloatArr(const FloatArr& src);
~FloatArr(); // Destructor FloatArr& operator=( const FloatArr&); // Assignment
int length() const { return cnt; }
// Subscript operators:
float& operator[](int i) throw(BadIndex);
float operator[](int i) const throw(BadIndex);
// Methods to append a float value // or an array of floats:
void append( float val);
void append( const FloatArr& v);
Trang 9FloatArr& operator+=( float val)
{
append( val); return *this;
}
FloatArr& operator+=( const FloatArr& v)
{
append(v); return *this;
}
// Methods to insert a float value
// or an array of float values:
void insert( float val, int pos) throw(BadIndex);
void insert(const FloatArr& v,int pos) throw(BadIndex); void remove(int pos) throw(BadIndex); // Remove
// at pos
// Output the array
friend ostream& operator<<( ostream& os,
const FloatArr& v) {
int w = os.width(); // Save field width
for( float *p = v.arrPtr; p < v.arrPtr + v.cnt; ++p) {
os.width(w); os << *p;
}
return os;
}
};
#endif // _FLOATARR_
//
-// floatArr.cpp
// Implementing the methods of FloatArr
//
-#include "floatArr.h"
// Constructors
-FloatArr::FloatArr( int n )
{
max = n; cnt = 0; // Sets max and cnt
arrPtr = new float[max]; // Allocates memory
}
FloatArr::FloatArr(int n, float val)
{
max = cnt = n;
arrPtr = new float[max];
for( int i=0; i < cnt; ++i)
arrPtr[i] = val;
}
Trang 10628 C H A P T E R 2 8 E X C E P T I O N H A N D L I N G
FloatArr::FloatArr(const FloatArr& src) {
max = src.max;
cnt = src.cnt;
arrPtr = new float[max];
for( int i = 0; i < cnt; i++ ) arrPtr[i] = src.arrPtr[i];
}
// Destructor -FloatArr::~FloatArr() {
delete[] arrPtr;
}
// Private functions to help enlarge the array
void FloatArr::expand( int newSize) {
if( newSize == max) return;
max = newSize;
if( newSize < cnt) cnt = newSize;
float *temp = new float[newSize];
for( int i = 0; i < cnt; ++i) temp[i] = arrPtr[i];
delete[] arrPtr;
arrPtr = temp;
}
FloatArr& FloatArr::operator=( const FloatArr& src ) {
if( this != &src ) // No self assignment! {
max = src.max;
cnt = src.cnt;
delete[] arrPtr; // Release memory,
arrPtr = new float[max]; // reallocate,
for( int i=0; i < cnt; i++) // copy elements arrPtr[i] = src.arrPtr[i];
} return *this;
}