Title: Exceptions,%20Templates,%20and%20the%20Standard%20Template%20Library%20(STL)
1Exceptions, Templates, and the Standard Template
Library (STL)
2Exceptions
- Indicate that something unexpected has occurred
or been detected - Allow program to deal with the problem in a
controlled manner - Can be as simple or complex as program design
requires - The line containing the throw statement is the
throw point - Control is passed to another part of the program
known as the exception handler - When an exception is thrown by a function, the
function aborts
3Coding for Exceptions
- int main()
-
- int numerator310,0,10
- int denominator3 2,10,0
- double answer
- for (int i0 ilt3i)
-
- answer divide(numeratori, denominatori)
- coutltltnumeratoriltlt" divided by
"ltltdenominatoriltlt" "ltltanswerltltendl -
- coutltltendlltltendl
- for (int i0 ilt3i)
-
- answer divide_throw(numeratori,
denominatori) - coutltltnumeratoriltlt" divided by
"ltltdenominatoriltlt" "ltltanswerltltendl -
- return 0
4Coding for Exceptions
- double divide(int n, int d)
-
- if (d0)
-
- coutltlt"ERROR Cannot divide by zero "
- return 0
-
- else
- return static_castltdoublegt(n)/d
-
- double divide_throw(int n, int d)
-
- if (d0)
-
- throw "ERROR Cannot divide by zero\n"
-
- else
- return static_castltdoublegt(n)/d
5Coding for Exceptions - Output
- Output from function divide
- 10 divided by 2 5
- 0 divided by 10 0
- ERROR Cannot divide by zero 10 divided by 0 0
- Output from function divide_throw
- 10 divided by 2 5
- 0 divided by 10 0
- This application has requested the Runtime to
terminate it in an unusual way. Please contact
the application's support team for more
information.
6Exceptions - Terminology
- Exception object or value that signals an error
- Throw an exception send a signal that an error
has occurred - throw followed by an argument, is used to throw
an exception - Catch/Handle an exception process the exception
interpret the signal - try followed by a block , is used to invoke
code that throws an exception - catch followed by a block , is used to
detect and process exceptions thrown in preceding
try block. Takes a parameter that matches the
type thrown.
7Exceptions Flow of Control
- A function that throws an exception is called
from within a try block - If the function throws an exception, the function
terminates and the try block is immediately
exited. - A catch block to process the exception is
searched for in the source code immediately
following the try block. - If a catch block is found that matches the
exception thrown, it is executed. - If no catch block that matches the exception is
found, the program terminates.
8From Program 16-1
9From Program 16-1
THIS WORKS in CodeBlocks char msg msg
"ERROR Cannot divide by zero.\n" if
(denominator 0) throw msg
10What Happens in the Try/Catch Construct
11What if no exception is thrown?
12Catch Exception and Reprompt
- int main()
-
- int num1, num2 // To hold two numbers
- double quotient // To hold the quotient of
the numbers - bool goodResult //test if no exception thrown
- do
- cout ltlt "Enter two numbers "
- cin gtgt num1 gtgt num2
- goodResulttrue
- try
- quotient divide(num1, num2)
- cout ltlt "The quotient is " ltlt quotient ltlt
endl -
-
- catch (char exceptionString)
- goodResultfalse
- cout ltltexceptionString
13Exceptions - Notes
- An integer can be thrown to signal a predefined
error code - try
- quotient divide(num1, num2)
- cout ltlt "The quotient is " ltlt quotient ltlt
endl -
- catch (int exceptionInt)
- goodResultfalse
- cout ltltError codeltltexceptionInt
-
- In the function write
- if (denominator 0) throw 333
- and then look up the code in a library or table
14Exceptions - Notes
- Predefined functions such as new may throw
exceptions - The value that is thrown does not need to be used
in catch block. - in this case, no name is needed in catch
parameter definition - catch block parameter definition does need the
type of exception being caught
15Exception Not Caught?
- An exception will not be caught if
- it is thrown from outside of a try block or,
- there is no catch block that matches the data
type of the thrown exception - If an exception is not caught, the program will
terminate
16Exceptions and Objects
- An exception class can be defined in a class and
thrown as an exception by a member function - An exception class may have
- no members used only to signal an error
- members pass error data to catch block
- A class can have more than one exception class
17Exception class definition
18(No Transcript)
19(No Transcript)
20Program 16-2 Output
21Handling Multiple Exceptions
- To differentiate between a negative width and
length, two classes can be created and each
called based on the type of error - In Rectangle.h include
- public
- class NegativeWidth // Exception class for
a negative width - class NegativeLength // Exception class
for a negative length - and in main change the try blocks to the
following - try
-
- myRectangle.setWidth(width)
- myRectangle.setLength(length)
- cout ltlt "The area of the rectangle is ltlt
myRectangle.getArea() ltlt endl -
- catch (RectangleNegativeWidth)
- coutltlt"Error A negative value was given "ltlt
"for the rectangle's width.\n" -
- catch (RectangleNegativeLength)
- coutltlt"ErrorA negative value was given "ltlt
"for the rectangle's length.\n" -
22Recovering From Exceptions
- Within the catch block, prompt the user to
re-enter the correct length or width
// Get the rectangle's width. cout ltlt "Enter the
rectangle's width " cin gtgt width // Store
the width in the myRectangle object. while
(tryAgain) try myRectangle.setWidth(width
) // If no exception was thrown, then the
// next statement will execute. tryAgain
false catch (RectangleNegativeWidth)
cout ltlt "Please enter a non-negative width "
cin gtgt width
// Get the rectangle's length. cout ltlt "Enter the
rectangle's length " cin gtgt length // Store
the length in the myRectangle object. tryAgain
true while (tryAgain) try
myRectangle.setLength(length) // If no
exception was thrown, then the // next
statement will execute. tryAgain false
catch (RectangleNegativeLength)
cout ltlt "Please enter a non-negative length "
cin gtgt length
23Recovering From Exceptions
Enter the rectangle's width -4 Please enter a
non-negative width -6 Please enter a
non-negative width 6 Enter the rectangle's
length -9 Please enter a non-negative length
9 The rectangle's area is 54
24 Extracting Data from the Exception Class
- Sometimes, we want an exception object to pass
data back to the exception handler - We want the Rectangle class not only to signal
when a negative value was entered, but to pass
back that value as well - This can be accomplished by expanding the
exception class with members in which data can be
stored. For example -
class NegativeWidth private int value public NegativeWidth(int val) value val int getValue() const return value Which is thrown by throw NegativeWidth(w) And caught by catch (RectangleNegativeWidth e) coutltlt "Error "ltlte.getValue()ltlt " is an invalid value for the" ltlt" rectangle's width.\n"
25What Happens After catch Block?
- Once an exception is thrown, the program cannot
return to throw point. The function executing
throw terminates (does not return), other calling
functions in try block terminate, resulting in
unwinding the stack - If an exception is thrown by the member function
of a class object, then the class destructor is
called - If objects were created in the try block and an
exception is thrown, they are destroyed.
26Nested try Blocks
- try/catch blocks can occur within an enclosing
try block - Exceptions caught at an inner level can be passed
up to a catch block at an outer level - catch ( )
-
- ...
- throw // pass exception up
- // to next level
27Nested try Blocks
- include ltiostreamgt
- using namespace std
- void doA()
- void doB()
- int main()
-
- char exception1
- try
- doA()
-
- catch(char exception1)
- coutltlt"Exception 1 handled in main"ltltendl
-
- return 0
-
void doA() char exception1 try
doB() catch(char exception1)
coutltlt"Exception 1 in doA(),rethrown
ltltendl throw void doB() char
exception1 try throw exception1
catch(char exception1)
coutltlt"Exception 1 in doB(),rethrown
ltltendl throw
Exception 1 in doB(),rethrown Exception 1 in
doA(),rethrown Exception 1 in main, handled in
main
28Handling the bad_alloc Exception
- When the new operator is unable to allocate the
requested amount of memory, a bad_alloc exception
is thrown. It can be handled as follows - include ltiostreamgt
- include ltnewgt // Needed for bad_alloc
- using namespace std
- int main()
- double ptr // Pointer to double
- try
- ptr new double 1000000000
- catch (bad_alloc)
- cout ltlt "Insufficient memory.\n"
- return 0
29Function Templates
- Function template a generic function that can
work with any data type. - It is a template and by itself does not cause
memory to be used - An actual instance of the function is created in
memory when the compiler encounters a call to the
template function - The programmer writes the specifications of the
function, but substitutes parameters for data
types - When called, compiler generates code for specific
data types in function call
30Function Template Example
template prefix
- template ltclass Tgt
- T square(T num)
-
- return num num
generic data type
type parameter
What gets generated when square is called with an int What gets generated when square is called with a double
int square(int num) return num num double square(double num) return num num
31Function Template Example
- template ltclass Tgt
- T square(T num)
-
- return num num
-
- Call a template function in the usual manner
- int ival 3
- double dval 12.5
- cout ltlt sqaure(ival) // displays 9
- cout ltlt sqaure(dval) // displays 156.25
32Function Template Swap Example
- include ltiostreamgt
- using namespace std
- template ltclass Tgt
- void swapVars(T var1, T var2)
-
- T temp
- temp var1
- var1 var2
- var2 temp
-
33Function Template Swap Example
- int main()
- char firstChar, secondChar // Two chars
- int firstInt, secondInt // Two ints
- double firstDouble, secondDouble // Two
doubles - // Get and swapVars two chars
- cout ltlt "Enter two characters "
- cin gtgt firstChar gtgt secondChar
- swapVars(firstChar, secondChar)
- cout ltlt firstChar ltlt " " ltlt secondChar ltlt
endl - // Get and swapVars two ints
- cout ltlt "Enter two integers "
- cin gtgt firstInt gtgt secondInt
- swapVars(firstInt, secondInt)
- cout ltlt firstInt ltlt " " ltlt secondInt ltlt endl
- // Get and swapVars two doubles
- cout ltlt "Enter two floating-point numbers "
34Function Template Notes
- Can define a template to use multiple data types
- templateltclass T1, class T2gt
- Example
- templateltclass T1, class T2gt
- // T1 and T2 will be replaced in the called
function - //with the data types of the arguments
- double mpg(T1 miles, T2 gallons) return miles /
gallons
35Function Template Notes
- include ltiostreamgt
- using namespace std
- template ltclass T1, class T2gt
- int largest(const T1 var1, T2 var2)
-
- if (sizeof(var1) gt sizeof(var2))
- return sizeof(var1)
- else
- return sizeof(var2)
-
- int main()
- int i 0
- char c ' '
- float f 0.0
- double d 0.0
-
- cout ltlt "Comparing an int and a double, the
largest\n"
Comparing an int and double, the largest of the
two is 8 bytes Comparing a char and a float, the
largest of the two is 4 bytes
36Function Template Notes
- Function templates can be overloaded Each
template must have a unique parameter list - template ltclass Tgt
- T sum(T val1, T val2)
- return val1 val2
- template ltclass Tgt
- T sum(T val1, T val2, Tval3)
- return val1 val2 val3
37Defining Your Own Templates
- Templates are often appropriate for multiple
functions that perform the same task with
different parameter data types - Develop function using usual data types first,
then convert to a template - add template prefix template ltclass Tgt
- convert data type names in the function to a type
parameter (i.e., a T type) in the template
38Class Templates
- Classes can also be represented by templates.
When a class object is created, type information
is supplied to define the type of data members of
the class. - Unlike functions, classes are instantiated by
supplying the type name (int, double, string,
etc.) at object definition
39Class Template Example
- template ltclass Tgt
- class grade
-
- private
- T score
- public
- grade(T)
- void setGrade(T)
- T getGrade()
40Class Template Example
- Pass type information to class template when
defining objects - gradeltintgt testList20
- gradeltdoublegt quizList20
- Use as ordinary objects once defined
41 int main() Gradeltintgt testlist20 testlist
0.setGrade(98) testlist1.setGrade(85) test
list2.setGrade(93) for (int i0 ilt3 i)
coutltlttestlisti.getGrade()ltlt" " return 0
- include ltiostreamgt
- using namespace std
- template ltclass Tgt
- class Grade
-
- private
- T score
- public
- Grade(T)
- void setGrade(T)
- T getGrade()
-
- template ltclass Tgt
- GradeltTgtGrade(T s)
- score s
42Class Templates and Inheritance
- Class templates can inherit from other class
templates - template ltclass Tgt
- class Rectangle
- ...
- template ltclass Tgt
- class Square public RectangleltTgt
- ...
- Must use type parameter T everywhere base class
name is used in derived class
43Introduction to the
Standard Template Library
- Standard Template Library (STL) a library
containing templates for frequently used data
structures and algorithms - Not supported by many older compilers
44Standard Template Library
- Two important types of data structures in the
STL - containers classes that stores data and imposes
some organization on it - iterators like pointers mechanisms for
accessing elements in a container
45Containers
- Two types of container classes in STL
- sequence containers organize and access data
sequentially, as in an array. These include
vector, deque, and list - vector efficiently inserts values to its end,
insertions at other points is not as efficient - deque efficiently inserts values to its front
and end, not as efficient at inserting at other
points - list efficiently inserts values anywhere
doesnt provide random access - associative containers use keys to allow data
elements to be quickly accessed. These include
set, multiset, map, and multimap
46Containers
- associative containers use keys to allow data
elements to be quickly accessed. These include
set, multiset, map, and multimap - set stores a set of keys, no duplicates
- multiset stores a set of keys, duplicates
allowed - map map a set of keys to data elements only
one key per data, no duplicates - multimap - map a set of keys to data elements
many keys per data element are allowed,
duplicates are allowed
47Iterators
- Generalization of pointers, used to access
information in containers - Four types
- forward (uses )
- bidirectional (uses and -- )
- random-access
- input (can be used with cin and istream objects)
- output (can be used with cout and ostream
objects) - vectors and deques require random access
iterators lists, sets, multisets, maps and
multimaps require bidirectional iterators
48Algorithms
- STL contains algorithms implemented as function
templates to perform operations on containers. - Requires algorithm header file
- algorithm includes
binary_search count
for_each find
find_if max_element
min_element random_shuffle
sort and others
49STL Example
- // A simple demonstration of STL algorithms
- include ltiostreamgt
- include ltvectorgt // Required for the vector
type - include ltalgorithmgt // Required for STL
algorithms - using namespace std
- int main()
-
- int count // Loop counter
- // Define a vector object.
- vectorltintgt vect
- // Use push_back to push values into the
vector. - for (count 0 count lt 10 count)
- vect.push_back(count)
- // Display the vector's elements.
- cout ltlt "The vector has " ltlt vect.size()
50STL Example
// Randomly shuffle the vector's contents.
random_shuffle(vect.begin(), vect.end()) //
Display the vector's elements. cout ltlt "The
elements have been shuffled\n" for (count
0 count lt vect.size() count) cout ltlt
vectcount ltlt " " cout ltlt endl // Now
sort the vector's elements. sort(vect.begin(),
vect.end()) // Display the vector's elements
again. cout ltlt "The elements have been
sorted\n" for (count 0 count lt
vect.size() count) cout ltlt vectcount
ltlt " " cout ltlt endl // Now search for an
element with the value 7. if
(binary_search(vect.begin(), vect.end(), 7))
cout ltlt "The value 7 was found in the
vector.\n" else cout ltlt "The value 7
was not found in the vector.\n" return 0
51STL Example - Output
The vector has 10 elements. Here they are 0 1 2
3 4 5 6 7 8 9 The elements have been shuffled 8
1 9 2 0 5 7 3 4 6 The elements have been
sorted 0 1 2 3 4 5 6 7 8 9 The value 7 was found
in the vector.