14 . Exception Handling: Mechanism and Usage Exception Handling Synchronous Errors Asynchronous Errors An Example function : Call may result in an error double sqrt(int number); Traditional Error Handling · Exit the program · Return an error value · Ignore error and continue · call a function in case of error
Exception Handling in C++ throw - try - catch ! class InvalidNumber { }; void main() { class DivisionByZero { }; try { expr(3, 0); double expr(int num1, int num2) } { catch(InvalidNumber&) { if (num1 < 0) cerr << "Error: Invalid Number\n"; throw InvalidNumber(); } if (num2 == 0) catch(DivisionByZero&) { throw DivisionByZero(); cerr << "Error: Division by Zero\n"; return sqrt(num1)/num2; } } } The throw/catch mechanism catch(E3&) may throw catch(...) { E1, E2, or //Do some { E3 //Gracefully // thing about catch(E2&) // the // inform user {... // exception } rethrow; } }
Example of Exception Handling // The Switch class represents an Electric Switch. It could be turned On or Off. class SwitchAlreadyOn {}; // Exception Class class SwitchAlreadyOff {}; // Exception Class class Switch { enum {OFF=0, ON}; unsigned int position; public: Switch(); // Default is OFF void TurnOn(); // Purpose: Turns on the Switch // Requirement: Switch should be Off // Promise: Will turn the Switch On // Exception: If already On, throws SwitchAlreadyOn void TurnOff(); // Purpose: Turns off the Switch // Requirement: Switch should be On // Promise: Will turn the Switch Off // Exception: If already Off, throws SwitchAlreadyOff const char* getPosition() const; // Purpose: Gives the position of Switch // Requirement: Nothing // Promise: Will return the position as a string. // Exception: Nothing }; Example Continued... #include <Switch.h> Switch::Switch(){ position = OFF; } void Switch::TurnOn() // Turns on the Switch // If already on, throws SwitchAlreadyOn { if (position == ON) throw SwitchAlreadyOn(); position = ON; } void Switch::TurnOff() // Turns off the Switch // If already Off, throws SwitchAlreadyOff { if (position == OFF) throw SwitchAlreadyOff(); position = OFF; } const char* Switch::getPosition() const { if (position == OFF) return "Off"; return "On"; }
Exception handling &Memory Leaks • Pay attention to when an exception may be thrown • If a call throws exception, remaining code may not be executed • If you create objects on stack, these are released - safe • Objects created on heap may result in leak Throwing built-in Types • You may thrown just about any thing as an exception int size … if (size > max) throw size; …
Throwing Objects • When objects are thrown as exceptions, copies of the objects are made • Be very mindful of resources used and shared Throwing References • You may thrown references • Minimizes the overhead of copy construction
Throwing Pointers • Similar to passing by reference • Again, use Caution Grouping Exceptions • You may build a hierarchy of exceptions classes • One may catch for a general exception, a specific exception or a combination of that • While catching multiple exceptions from a group, start with specific ones before catching general ones class DiskAccessError {}; class DiskReadError : public DiskAccessError {}; … catch(DiskReadError daeErr) {// Catches Only disk read errors } catch(DiskAccessError daeErr) { // Catches any DiskAccessError{ }
Re-Throwing Exceptions • Your catch code may – make an effort to handle the exception – may log the exception received • May re-throw the exception to its caller Catching just about any thing • Most justifiable use of ellipsis … • Helps “catch all” case to prevent unhandled exceptions resulting in crash • Use judiciously
Lab Work: Details provided on-line.
Recommend
More recommend