Exception Handling - Example 16 - Using Standard Exceptions and Deriving Your Own
#pragma warning( disable : 4996 4290)
#include <exception>
#include <stdexcept>
#include <iostream>
#include <cmath> // for sqrt()
#include <cstring>
#include <cstdlib>
#include <sstream> // for istreamstream/ostringstream
#include <climits> // for SHRT_MAX
#include <typeinfo> // for typeid operator
using namespace std;
// This operator<<() function get used in the catches
ostream& operator<<(ostream& out, const exception& error)
{
out << "I caught an error of type: " << typeid(error).name() << endl
<< "Message: " << error.what() << endl;
return out;
}
class my_domain_error : public domain_error
{
public:
my_domain_error(const char* message) : domain_error(message)
{}
const char* what() const throw () // Note: emptry throw required for Dev-C++ (GNU ver 3.4.2)
{
static char temp[128];
strcpy(temp,"my_domain_error: ");
strcat(temp,domain_error::what());
return temp;
}
};
double mysqrt1(double number) throw (domain_error)
{
if (number < 0) throw domain_error("mysqrt1 error: argument is negative");
return sqrt(number);
}
double mysqrt2(double number) throw (my_domain_error)
{
if (number < 0) throw my_domain_error("mysqrt2 error: argument is negative");
return sqrt(number);
}
// Derive the zero_denominator class from invalid_argument
class zero_denominator : public invalid_argument
{
public:
zero_denominator() : invalid_argument("Error: zero denominator") {}
};
class fraction
{
int numerator, denominator;
public:
fraction(int n = 0, int d = 1) : numerator(n), denominator(d)
{
if (d == 0 ) throw zero_denominator();
}
};
// convert a hexadecimal string to unsigned int
unsigned hex_string_to_unsigned(string hextext) throw (invalid_argument)
{
if (hextext.find_first_not_of("0123456789abcdefABCDEF") != string::npos) {
throw invalid_argument(string("Invalid hexadecimal char in: " ) + hextext);
}
istringstream sin(hextext);
unsigned number;
sin >> hex >> number;
return number;
}
// returns sum of two shorts, optional check to make sure sum is valid short
short add2shorts(short one, short two, bool check_limit = false) throw (overflow_error)
{
if (check_limit) {
if (static_cast(one) + two > SHRT_MAX) { // SHRT_MAX is max value of short int (32767)
ostringstream sout;
sout << "add2shorts failed with arguments " << one << " and " << two;
throw overflow_error(sout.str());
}
}
return one + two;
}
int main()
{
// test throw/catch of domain_error
try {
cout << "mysqrt1(2.0)=" << mysqrt1(2.0) << endl;
cout << "mysqrt1(-2.0)=" << mysqrt1(-2.0) << endl;
}
catch (const domain_error& error) {
cerr << "Line " << __LINE__ << ": " << error << endl;
}
// test throw/catch of logic_error
try {
cout << "mysqrt1(-2.0)=" << mysqrt1(-2.0) << endl;
}
catch (const logic_error& error) {
cerr << "Line " << __LINE__ << ": " << error << endl;
}
// test throw/catch of (base class) exception
try {
cout << "mysqrt1(-2.0)=" << mysqrt1(-2.0) << endl;
}
catch (const exception& error) {
cerr << "Line " << __LINE__ << ": " << error << endl;
}
// test throw/catch of my_domain_error
try {
cout << "mysqrt2(-2.0)=" << mysqrt2(-2.0) << endl;
}
catch (const my_domain_error& error) {
cerr << "Line " << __LINE__ << ": " << error << endl;
}
// test throw/catch of zero_denominator
try {
fraction F(2,0);
}
catch (const zero_denominator& error) {
cerr << "Line " << __LINE__ << ": " << error << endl;
}
// test throw/catch of invalid_argument
try {
cout << "hex abc=" << hex_string_to_unsigned(string("abc")) << endl;
cout << "hex abz=" << hex_string_to_unsigned(string("abz")) << endl;
}
catch (const invalid_argument& error) {
cerr << "Line " << __LINE__ << ": " << error << endl;
}
// test throw/catch of overflow_erro
try {
cout << "short 31000+32000=" << add2shorts(31000,32000) << endl;
cout << "short 31000+32000=" << add2shorts(31000,32000,true) << endl;
}
catch (const overflow_error& error) {
cerr << "Line " << __LINE__ << ": " << error << endl;
}
system ("pause");
return 0;
}
***** Program Output *****
MS Visual C++ 2008
mysqrt1(2.0)=1.41421
Line 102: I caught an error of type: class std::domain_error
Message: mysqrt1 error: argument is negative
Line 110: I caught an error of type: class std::domain_error
Message: mysqrt1 error: argument is negative
Line 118: I caught an error of type: class std::domain_error
Message: mysqrt1 error: argument is negative
Line 126: I caught an error of type: class my_domain_error
Message: my_domain_error: mysqrt2 error: argument is negative
Line 134: I caught an error of type: class zero_denominator
Message: Error: zero denominator
hex abc=2748
Line 143: I caught an error of type: class std::invalid_argument
Message: Invalid hexadecimal char in: abz
short 31000+32000=-2536
Line 152: I caught an error of type: class std::overflow_error
Message: add2shorts failed with arguments 31000 and 32000
***** Program Output *****
gnu g++ version 3.4.2
mysqrt1(2.0)=1.41421
Line 102: I caught an error of type: St12domain_error
Message: mysqrt1 error: argument is negative
Line 110: I caught an error of type: St12domain_error
Message: mysqrt1 error: argument is negative
Line 118: I caught an error of type: St12domain_error
Message: mysqrt1 error: argument is negative
Line 126: I caught an error of type: 15my_domain_error
Message: my_domain_error: mysqrt2 error: argument is negative
Line 134: I caught an error of type: 16zero_denominator
Message: Error: zero denominator
hex abc=2748
Line 143: I caught an error of type: St16invalid_argument
Message: Invalid hexadecimal char in: abz
short 31000+32000=-2536
Line 152: I caught an error of type: St14overflow_error
Message: add2shorts failed with arguments 31000 and 32000