Programming
Techniques Course
Version 1.0
© Copyright Eliyahu Brutman
Chapter 12 – Exceptions
Version 1.0
© Copyright Eliyahu Brutman
Exceptions and Design Patterns -
Introduction to Exception Handling
Definition: An exception is any unusual event, either erroneous or
not, detectable by either hardware or software, that may require
special processing
Without exception handling
When an exception occurs, control goes to the operating
system, where typically
an error message is displayed
the program is terminated
With exception handling
Programs are allowed to trap exceptions
There is a possibility to fix the problem and continuing
execution
© Copyright Eliyahu Brutman
3
Exceptions and Design Patterns -
Possible Naïve Solutions
Exit the Program
Isn’t it too strong
OS already does the same
Return Error Code
Need to check the return code for every call
Raise a Flag
Need to check the flag after every operation
Call a Special Code to Correct the Error
But when shall we call it?
© Copyright Eliyahu Brutman
4
Exceptions and Design Patterns -
Motivation
A mechanism which allows two components to survive runtime
program anomaly
Encountering such an anomaly (division by zero, access to an
array outside its bound, etc.), may need an immediate handling
The handling may reside in a different component, which we
need to communicate
The encountering components throws an exception
The handling code, catches the exception, and handles it
accordingly
© Copyright Eliyahu Brutman
5
Exceptions and Design Patterns -
Example
Lets consider class stack
const int MAX_ELEM=10;
template <typename T, int size=MAX_ELEM>
class Stack {
T
m_arr[size];
int
m_index;
public:
Stack() : m_index(0) {}
void Push(T elemP) {
m_arr[m_index] = elemP;
m_index++;
}
T& Pop() {
m_index--;
return m_arr[m_index]; }
int Index() const {
return m_index; }
};
© Copyright Eliyahu Brutman
6
Exceptions and Design Patterns -
Exception Handling Syntax
Exception Handlers
try {
-- code that is expected to raise an exception
}
catch (formal parameter) {
-- handler code
}
...
© Copyright Eliyahu Brutman
7
Exceptions and Design Patterns -
Class Anomalies
What happens if we pop() an empty stack?
What happens if we push() on a full stack?
We decide that these situations need to be handled in a special
manner, since they are anomalies of the class behavior.
First we define classes of exceptions which may be thrown
class popOnEmpty { /* … */ }
class pushOnFull { /* … */ }
Upon anomaly detection, we will throw an exception
© Copyright Eliyahu Brutman
8
Exceptions and Design Patterns -
Example
Our code would now change
…
void Push(T elemP) {
if (m_index>=size)
throw pushOnFull(); // an object is throws
m_arr[m_index] = elemP;
m_index++;
}
T& Pop() {
if (m_index<=0)
throw popOnEmpty(); // an object is thrown
m_index--;
return m_arr[m_index]; }
…
};
No need to examine the returned value for checking for success.
© Copyright Eliyahu Brutman
9
Exceptions and Design Patterns -
Try…Catch Blocks
Wrap the code which needs to be “exception sensitive”, and
react to raised exceptions, in a try {…} catch {…} blocks
The client’s code look now as following
int main() {
try{
Stack<int> si;
si.Pop();
si.Push(5);
si.Pop();
}
catch (popOnEmpty) {
cout << "stack is empty !!" << endl;
}
};
© Copyright Eliyahu Brutman
10
Exceptions and Design Patterns -
Try…Catch Blocks
When exception is thrown, execution resumes in the “closest”
catch clause handling the exception.
If no catch clause exists capable of handling the exception,
program execution resumes at the terminate() function.
Variables declared within the try block cannot be referred to at
the catch clause, since they are local to the block.
11
int main() {
try{
Type declaration
Stack<int> si;
si.Pop();
si.Push(5);
si.Pop();
}
catch (popOnEmpty) {
cout << "stack is empty !!" << endl;
}
cout << “Execution resumes here” << endl;
};
© Copyright Eliyahu Brutman
Execution does
Not resume here
Exceptions and Design Patterns -
Exception-Handling Control Flow
© Copyright Eliyahu Brutman
12
Exceptions and Design Patterns -
Throwing Objects
Why throw an object?
Additional data encapsulated
An object is created upon invoking the throw statement
Can be created with additional data, passed to Ctor
Object is destroyed after the catch clause ends
© Copyright Eliyahu Brutman
13
Exceptions and Design Patterns -
Stack Unwinding
Up the chain of nested function calls, a suitable catch clause is
searched for
Upon functions and compound statements exit, stack is being
unwound
Lifetime of local variables ends
Destructors are called
If no handler is supplied, terminate() is called
Since exception is a situation, where the program cannot
continue execution in a normal manner
By default terminate() calls abort()
Similar to function call behavior
But information to set up a function call is not available at
compile time, run-time support is needed
© Copyright Eliyahu Brutman
14
Exceptions and Design Patterns -
Re-throwing and Catch All
After some corrective action, a catch clause may throw an
exception to be further handled, passing the exception to
another catch clause, by throw.
General exception handling can be specified
catch(…) {
// place code here
}
If specified with combination, must be specified last, since
evaluation is evaluated in turn.
© Copyright Eliyahu Brutman
15
Exceptions and Design Patterns -
Exception Specification
Function interface need to be as precise as possible, it is the
contract between several codes
Client code may need to prepare for specific handling
Best is to provide exception specification with the method
declaration
This will help the compiler to check consistency, to check
that no other exceptions are thrown
It follows the function parameter list
© Copyright Eliyahu Brutman
16
Exceptions and Design Patterns -
Exception Specification
…
void Push(T elemP) throw(pushOnFull) {
if (m_index>=size)
throw pushOnFull(); // an object is throws
m_arr[m_index] = elemP;
m_index++;
}
T& Pop() throw(popOnEmpty) {
if (m_index<=0)
throw popOnEmpty(); // an object is thrown
m_index--;
return m_arr[m_index]; }
…
};
© Copyright Eliyahu Brutman
17
Exceptions and Design Patterns -
Nesting try Blocks
Exceptions are always handled by closest matching handler
try {
try {
throw 5;
} catch (int x)
{
cout << x << endl;
}
} catch (int x)
{
cout << x-5 << endl;
}
© Copyright Eliyahu Brutman
// exception will be caught here
18
Exceptions and Design Patterns -
Exceptions from Function Calls
No different from nested try blocks
Auto variables on stack are destroyed
Exception jumps to nearest handler
Allows exception handlers to be implemented far
away from where the problem was
May requires a knowledge of the issue packaged
in exception object for appropriate handling
© Copyright Eliyahu Brutman
19
Exceptions and Design Patterns -
Exception Hierarchies
Class types representing exceptions may be organized into
groups or hierarchies
Class Excp {}
Class stackExcp : public Excp {}
Class popOnEmpty : public stackExcp {}
Class pushOnFull : public stackExcp {}
Throwing an exception of type popOnEmpty may be caught by a
handler expecting its base
Therefore order should be handling more concrete types, and
then handling more generic types
Since handling is evaluated in order of specification, “first
match”
Ctors and Dtors are called in order like before
© Copyright Eliyahu Brutman
20
Exceptions and Design Patterns -
C++ Exception Hierarchy
bad_cast
exception
bad_typeid
logic_error
invalid_argument
length_error
out_of_range
© Copyright Eliyahu Brutman
bad_alloc
ios_base::failure
domain_error
bad_exception
range_error
runtime_error
underflow_error
overflow_error
21
Exceptions and Design Patterns -
Exceptions in Constructors
Constructors cannot return errors
Can throw exceptions
Must use care!
Destructors only called for fully constructed objects
Subobjects (member variables that are objects) will get
destroyed
If memory allocated dynamically in constructor, it could get
lost
Exceptions are automatically rethrown from constructors
© Copyright Eliyahu Brutman
22
Exceptions and Design Patterns -
Exceptions Example
A programmer-define ListException class
#include <exception>
#include <string>
using namespace std;
class ListException: public exception
{
public:
ListException (const string & message = “”)
: exception(message.c_str())
{}
}; // end ListException
© Copyright Eliyahu Brutman
23
Exceptions and Design Patterns -
1
2
3
4
5
6
7
8
9
10
11
12
13
24
25
26
27
28
29
// Fig. 13.1: fig13_01.cpp
// A simple exception-handling example that checks for
// divide-by-zero exceptions.
#include <iostream>
Define new exception class
(inherit from exception).
#include <exception>
Pass a descriptive message to
using namespace std;
the constructor.
// DivideByZeroException objects should be thrown by functions
// upon detecting division-by-zero exceptions
class DivideByZeroException : public exception {
public:
// constructor specifies default error message
DivideByZeroException::DivideByZeroException()
: exception( "attempted to divide by zero" ) {}
};
// end class DivideByZeroException
© Copyright Eliyahu Brutman
24
Exceptions and Design Patterns -
26
27
28
29
30
31
32
33
34
35
37
38
39
40
41
42
43
44
45
46
// perform division and throw DivideByZeroException object if
// divide-by-zero exception occurs
double quotient( int numerator, int denominator )
{
// throw DivideByZeroException if trying to divide by zero
if ( denominator == 0 )
throw DivideByZeroException(); // terminate function
}
// return division result
return static_cast< double >( numerator ) / denominator;
// end function quotient
int main()
{
int number1;
int number2;
double result;
If the denominator is zero, throw
a DivideByZeroException
object.
// user-specified numerator
// user-specified denominator
// result of division
cout << "Enter two integers (end-of-file to end): ";
© Copyright Eliyahu Brutman
25
Exceptions and Design Patterns -
47
48
49
50
51
52
53
54
56
57
58
59
60
61
62
63
64
65
66
67
68
26
// enable user to enter two integers to divide
while ( cin >> number1 >> number2 ) {
// try block contains code that might throw exception
// and code that should not execute if an exception occurs
try {
result = quotient( number1, number2 );
cout << "The quotient is: " << result << endl;
} // end try
// exception handler handles a divide-by-zero exception
catch ( DivideByZeroException ÷ByZeroException ) {
cout << "Exception occurred: "
<< divideByZeroException.what() << endl;
} // end catch
cout << "\nEnter two integers (end-of-file to end): ";
} // end while
Notice the structure of the try and catch blocks. The
catch block can catch DivideByZeroException
objects, and print an error message. If no exception
cout << endl;
return 0; // terminate normally occurs, the catch block is skipped.
Member function what returns the string describing the
} // end main
exception.
© Copyright Eliyahu Brutman
Exceptions and Design Patterns -
27
Enter two integers (end-of-file to end): 100 7
The quotient is: 14.2857
Enter two integers (end-of-file to end): 100 0
Exception occurred: attempted to divide by zero
Enter two integers (end-of-file to end): ^Z
fig13_01.cpp
output (1 of 1)
© Copyright Eliyahu Brutman
Exceptions and Design Patterns -
When TO Use Exceptions
Fix the problem and try again
Patch the problem and continue
Make a complex error mechanism simpler
Make code safer (catch fatal errors)
© Copyright Eliyahu Brutman
28
© Copyright 2026 Paperzz