The document discusses operator overloading and exception handling in C++. It describes how to overload operators like +, -, *, / by defining special functions for them and the advantages of doing so. It also explains how to handle exceptions using try, throw, and catch blocks to handle runtime errors.
This set of slides introduces the reader to a subset of the C++ Standard Library called the Standard Template Library (STL). The STL provides a collection of parameterized containers and algorithms, and it is the most successful example of an approach to programming called generic programming. In this presentation, we aim at studying the ideals and concepts of the STL by re-implementing small parts of the library. Specifically, we first show how we can discover requirements on types in order to devise generic algorithms. Then, we focus on how to make algorithms independent of containers through the pivotal abstraction of iterators. To this end, we replicate the standard algorithm for finding the minimum in a sequence (min_element), which we subsequently match with a custom forward iterator over intrusive linked lists of integers. Finally, we see how function objects can be used to customize containers and algorithms alike. This allows us to deepen our understanding of ordering relations, and, in particular, to introduce the concept of strict weak orderings.
An Introduction to Part of C++ STL for OI. Introduced the common use of STL algorithms and containers, especially those are helpful to OI.
Also with some examples.
This set of slides introduces the reader to a subset of the C++ Standard Library called the Standard Template Library (STL). The STL provides a collection of parameterized containers and algorithms, and it is the most successful example of an approach to programming called generic programming. In this presentation, we aim at studying the ideals and concepts of the STL by re-implementing small parts of the library. Specifically, we first show how we can discover requirements on types in order to devise generic algorithms. Then, we focus on how to make algorithms independent of containers through the pivotal abstraction of iterators. To this end, we replicate the standard algorithm for finding the minimum in a sequence (min_element), which we subsequently match with a custom forward iterator over intrusive linked lists of integers. Finally, we see how function objects can be used to customize containers and algorithms alike. This allows us to deepen our understanding of ordering relations, and, in particular, to introduce the concept of strict weak orderings.
An Introduction to Part of C++ STL for OI. Introduced the common use of STL algorithms and containers, especially those are helpful to OI.
Also with some examples.
Java 8 Stream API. A different way to process collections.David Gómez García
A look on one of the features of Java 8 hidden behind the lambdas. A different way to iterate Collections. You'll never see the Collecions the same way.
These are the slides I used on my talk at the "Tech Thursday" by Oracle in June in Madrid.
Twins: Object Oriented Programming and Functional ProgrammingRichardWarburton
Object-Oriented Programming has well established design principles, such as SOLID. For many developers architecture and functional programming are at odds with each other: they don’t know how their existing tricks of the trade convert into functional design. This problem becomes worse as hybrid languages such as Java 8 or Scala become common. We’ll talk about how functional programming helps you implement the SOLID principles, and how a functional mindset can actually help you achieve cleaner and simpler OO design.
Implementation details and performance traits of generics in .NET, Java and C++. Presentation for the Jerusalem .NET/C++ User Group by Sasha Goldshtein.
It's not your mother's C++ anymore. Manual memory management, tedious loops, difficult-to-use STL algorithms -- are all a thing of the past now. The new C++ 11 standard contains a huge number of improvements to the C++ core language and standard library, and can help C++ developers be more productive.
In this session we will discuss the major features of C++ 11, including lambda functions, type inference for local variables, range-based for loops, smart pointers, and more. We will see how to use these features effectively to modernize your existing C++ programs and how to develop in the modern C++ style.
Java 8 Stream API. A different way to process collections.David Gómez García
A look on one of the features of Java 8 hidden behind the lambdas. A different way to iterate Collections. You'll never see the Collecions the same way.
These are the slides I used on my talk at the "Tech Thursday" by Oracle in June in Madrid.
Twins: Object Oriented Programming and Functional ProgrammingRichardWarburton
Object-Oriented Programming has well established design principles, such as SOLID. For many developers architecture and functional programming are at odds with each other: they don’t know how their existing tricks of the trade convert into functional design. This problem becomes worse as hybrid languages such as Java 8 or Scala become common. We’ll talk about how functional programming helps you implement the SOLID principles, and how a functional mindset can actually help you achieve cleaner and simpler OO design.
Implementation details and performance traits of generics in .NET, Java and C++. Presentation for the Jerusalem .NET/C++ User Group by Sasha Goldshtein.
It's not your mother's C++ anymore. Manual memory management, tedious loops, difficult-to-use STL algorithms -- are all a thing of the past now. The new C++ 11 standard contains a huge number of improvements to the C++ core language and standard library, and can help C++ developers be more productive.
In this session we will discuss the major features of C++ 11, including lambda functions, type inference for local variables, range-based for loops, smart pointers, and more. We will see how to use these features effectively to modernize your existing C++ programs and how to develop in the modern C++ style.
#ifndef RATIONAL_H if this compiler macro is not defined #def.pdfexxonzone
#ifndef RATIONAL_H // if this compiler macro is not defined
#define RATIONAL_H // then define it so this file will not be processed again
#include \"stdafx.h\" // use only for Microsoft Visual Studio C++
#include
using namespace std;
class Rational
{
// Friend functions are actually declared outside the scope of the
// class but have the right to access public and private data and
// member function members that belong to the class. The friend
// function below gives the << operator for ostreams (including cout)
// the ability to output a Rational object by accessing its member data.
friend ostream &operator<< (ostream &out, Rational const &r);
public:
Rational(int num = 0, int denom = 1); // also provides default constructor
Rational add(Rational right);
Rational operator+ (Rational right); // + addition operator
Rational operator+= (Rational right); // += addition assignment operator
Rational operator- (Rational right); // + addition operator
Rational operator-= (Rational right); // += addition assignment operator
void display();
operator double() const; // convert Rational to double
private:
int numerator;
int denominator;
// helper functions are private and not accessible by the main program
int LCD(int v1, int v2);
Rational setRational(int n, int d);
};
#endif
#include \"stdafx.h\"
#include
#include \"Rational.h\"
using namespace std;
// By using the default parameter settings in Rational.h, this
// constructor also provides the default constructor Rational()
Rational::Rational(int num, int denom)
{
setRational(num, denom); // set numerator and denominator, reduce fraction, fix the sign
}
// Helper function to fix a zero denominator and fix the sign if denominator is negative
Rational Rational::setRational(int n, int d) // helper function
{
numerator = n;
denominator = d;
// if denominator == 0 then set it = 1
if (denominator == 0)
denominator = 1;
if (denominator < 0) // if denominator is neg, multiply num and denom by -1
{
numerator = -numerator; // fix sign of numerator +/-
denominator = -denominator; // denominator always +
}
int lcd = LCD(numerator, denominator);
if (denominator != 0)
{
numerator /= lcd;
denominator /= lcd;
}
return *this; // return the current object
}
// find the lowest common divisor using a recursive function
int Rational::LCD(int v1, int v2)
{
if (v2 == 0) return v1;
else return LCD(v2, v1%v2);
}
Rational Rational::add(Rational right)
{
int newNumerator;
int newDenominator;
newNumerator = numerator*right.denominator + right.numerator*denominator;
newDenominator = denominator * right.denominator;
// create a new Rational object and return it
return setRational(newNumerator, newDenominator);
}
// the operator+ method does the same thing as the add method
Rational Rational::operator+ (Rational right)
{
int newNumerator;
int newDenominator;
newNumerator = numerator*right.denominator + right.numerator*denominator;
newDenominator = denominator * right.denominator;
// create a new Rational object and return it
return .
(Rational Class) - use the original files to create the new progra.pdfalstradecentreerode
(Rational Class) - use the original files to create the new program
Create a class called Rational (separate the files as shown in the chapter) for performing
arithmetic with fractions. Write a program to test your class. Use integer variables to represent
the private data of the class-the numerator and the denominator. Provide a constructor that
enables an object of this class to be initialized when it's declared. The constructor should contain
default values in case no initializers are provided and should store the fraction in reduced form.
For example, the fraction 2/4 would be stored in the object as 1 in the numerator and 2 in the
denominator. Provide public member functions that perform each of the following tasks:
1.Make an overloaded operator of the + symbol for the add method - Adds two Rational
numbers. The result should be stored in reduced form.
2. Make an overloaded operator of the - symbol for the subtract method - Subtracts two Rational
numbers. Store the result in reduced form.
3. Make an overloaded operator of the * symbol for the multiply method - Multiples two
Rational numbers. Store the result in reduced form.
4. Make an overloaded operator of the / symbol for the divide method - Divides two Rational
numbers. The result should be stored in reduced form.
5.NO CHANGES TO THIS (toRationalString - optional uses iostream from previous chapter -
extra credit) - Returns a string representation of a Rational number in the form a/b, where a is the
numerator and b is the denominator.
6.NO CHANGES TO THIS | display - Display the Rational number a/b.
7.NO CHANGES TO THIS | toDouble - Returns the Rational number as a double.
(make sure the driver tests out all the overloaded operators)
code to copy---
rational.h--
#ifndef RATIONAL_H
#define RATIONAL_H
#include
class Rational {
private:
int numerator;
int denominator;
public:
Rational (int num = 0. int den = 1);
Rational add (const Rational& other) const;
Rational subtract (const Rational& other) const;
Rational multiply(const Rational& other) const;
Rational divide (const Rational& other) const;
std: :string toRationalString() const;
void display() const;
double toDouble() const;
};
#endif
rational.cpp--
#include Rational.h
#include
#include
int gcd(int a, int b) {
return b == 0 ? A : gcd(b, a % b);
}
Rational::Rational(int num, int den) {
int gcd_num_den = gcd(num, den);
numerator = num / gcd_num_den;
denominator = den / gcd_num_den;
}
Rational Rational::add(const Rational& other) const {
int new_num = numerator * other.denominator + other.numerator * denominator;
int new_den = denominator * other.denominator;
return Rational(new_num, new_den);
}
Rational Rational::subtract(const Rational& other) const {
int new_num = numerator * other.denominator - other.numerator * denominator;
int new_den = denominator * other.denominator;
return Rational(new_num, new_den);
}
Rational Rational::multiply(const Rational& other) const {
int new_num = numerator * other.numerator;
int new_den = denomina.
I am Baddie K. I am a C++ Homework Expert at cpphomeworkhelp.com. I hold a Masters in Programming from The University of Queensland. I have been helping students with their homework for the past 9 years. I solve homework related to C++. Visit cpphomeworkhelp.com or email info@cpphomeworkhelp.com. You can also call on +1 678 648 4277 for any assistance with C++ Homework.
This is an PPT of C++. This includes the topic of Parameter such as"Reference Parameter, Passing object by reference, constant parameter & Default parameter. "
Assignment 13/assg-13.cppAssignment 13/assg-13.cpp/**
* @author Jane Programmer
* @cwid 123 45 678
* @class COSC 2336, Spring 2019
* @ide Visual Studio Community 2017
* @date April 8, 2019
* @assg Assignment 13
*
* @description Assignment 13 Dictionaries and Hash table
* implementations.
*/
#include<cassert>
#include<iostream>
#include"KeyValuePair.hpp"
#include"Employee.hpp"
#include"HashDictionary.hpp"
usingnamespace std;
/** main
* The main entry point for this program. Execution of this program
* will begin with this main function.
*
* @param argc The command line argument count which is the number of
* command line arguments provided by user when they started
* the program.
* @param argv The command line arguments, an array of character
* arrays.
*
* @returns An int value indicating program exit status. Usually 0
* is returned to indicate normal exit and a non-zero value
* is returned to indicate an error condition.
*/
int main(int argc,char** argv)
{
// -----------------------------------------------------------------------
cout <<"----- testing Employee record and KeyValuePair class -----------"<< endl;
KeyValuePair<int, string> pair(42,"blue");
cout <<"test key: "<< pair.key()<< endl;
assert(pair.key()==42);
cout <<"test value: "<< pair.value()<< endl;
assert(pair.value()=="blue");
int id =3;
Employee e(id,"Derek Harter","1234 Main Street, Commerce TX",12345.67);
cout << e << endl;
assert(e.getId()==3);
assert(e.getName()=="Derek Harter");
cout << endl;
// -----------------------------------------------------------------------
cout <<"-------------- testing quadratic probing -----------------------"<< endl;
constint TABLE_SIZE =7;
HashDictionary<int,Employee> dict(TABLE_SIZE, EMPTY_EMPLOYEE_ID);
cout <<"Newly created hash dictionary should be empty, size: "<< dict.size()<< endl;
assert(dict.size()==0);
int probeIndex =0;
//cout << "probe index: " << probeIndex
// << " returned probe value: " << dict.probe(id, probeIndex)
// << endl;
//assert(dict.probe(id, probeIndex) == 2);
probeIndex =1;
//cout << "probe index: " << probeIndex
// << " returned probe value: " << dict.probe(id, probeIndex)
// << endl;
//assert(dict.probe(id, probeIndex) == 5);
probeIndex =5;
//cout << "probe index: " << probeIndex
// << " returned probe value: " << dict.probe(id, probeIndex)
// << endl;
//assert(dict.probe(id, probeIndex) == 37);
cout << endl;
// -----------------------------------------------------------------------
cout <<"-------------- testing mid-square hashing ----------------------"<< endl;
// the following asserts will only work for 32 bit ints, leave asserts
// commented out if you have 64 bit asserts
cout <<"Assuming 32 bit (4 byte) ints for these tests: "<<sizeof(int)<< endl;
assert(sizeof(int)==4);
//id = 3918;
//cout << "hash key: " << id
// << " returned hash value: " << dict.hash(id)
// << endl; ...
2. Learning Objectives
Operator Overloading
To understand what is operator overloading
To understand the advantage of operator overloading
To understand how to overload operators as functions
Exception handling
To understand what is exception
To realize the advantages of exception handling
To understand the use of try, throw and catch block
To understand how exception propagation works
To understand how to wrote multiple catch blocks and
exception matching
2
3. Operator Overloading
• Add capability to an operator via writing a new "special
function" for the same operator but with different data
types and combinations of parameters.
• For example, C++'s operator '+':
• C++ has built-in support for using operator '+' to add
int or double, and also for concatenating string.
• However using operator '+' to add 2 objects of your
(user-defined) class is not automatically supported.
• We can write a "function" to make C++ support
adding 2 objects of user-defined class. This process
is called operator overloading.
3
4. Operator Overloading Advantage
• It provides a simpler way for doing some operations on
user-defined classes.
• Consider the following Rational class which
represents a rational/fraction number, e.g. 1/2, 2/3:
class Rational {
int num; // numerator
int den; // denominator
public:
Rational (int num=0, int den=1) : num(num), den(den) {}
int getNum() const { return num; }
int getDen() const { return den; }
};
Rational multiply (const Rational& r1, const Rational& r2) {
int n = r1.getNum() * r2.getNum();
int d = r1.getDen() * r2.getDen();
return Rational (n, d);
}
4
5. Operator Overloading Advantage
• To multiply rational numbers e.g. 1/2 * 1/3 * 5/6 =
5/36, we can use the method multiply(), but it
looks more complex.
int main() {
Rational r1(1,2), r2(1,3), r3(5,6), r4;
r4 = multiply(r1, multiply(r2,r3)); Complex
...
• If we overload multiply operator '*', we can write:
int main() {
Rational r1(1,2), r2(1,3), r3(5,6), r4; Simple &
r4 = r1 * r2 * r3; easy to
... understand
5
6. C++ Operators
Operators in C++ are divided into 2 categories based on the
number of arguments they accept:
• Unary operators accept one argument
• x++, --x, !x, etc.
• Binary operators accept two arguments
• x+y, x-y, x*y, x<y, x=y, etc.
7. C++ Operators
Some unary operators can be used as both prefix and postfix
operators, e.g. increment ‘++’ and decrement ‘--’ operators.
int a = b = 0;
++a; // a = 1
prefix b = ++a; // b = 2, a = 2
cout << "a is:" << a; // a is 2
cout << "b is:" << b; // b is 2
postfix b = a++; // b = 2
// a = 3
cout << "a is:" << a; // a is 3
cout << "b is:" << b; // b is 2
7
8. How to Overload Operators?
We overload an operator by writing a special function with
the keyword operatorS, where S is an operator symbol (+, -
, *, /, !, ++, etc.).
We should overload an operator in a sensible way and meet
general expectation, e.g. don't overload '*' operator to
perform division.
returntype operatorS (parameters) {
...
return something;
}
// For our Rational number multiplication.
returntype operator* (parameters) {
...
return something;
8
}
9. How to Overload Operators?
The number of parameters depend whether the overloaded
operator is unary or binary.
• Unary operator has 1 parameter.
• Binary operator has 2 parameters.
Since operator '*' is a binary operator hence the number of
parameter is 2.
We are multiplying 2 Rational objects and expecting the
result is also a Rational object, hence the data type of
both parameter and return type should be Rational.
// For our Rational number multiplication.
Rational operator* (Rational, Rational) {
...
return Rational(); // return a new object.
} 9
10. Parameters & Return Types
• For parameters, use references whenever possible
(especially when the parameter is a big object).
• Always use pass-by-const reference when the argument will
not be modified.
• Always try to follow the spirit of the built-in implementations,
e.g. comparison operators (==, !=, >, etc) generally return a
bool, so an overloaded version should do the same.
• Operators that return a reference to the original object
should return a non-const reference to ensure that the result
can be modified in a later operation., e.g. <<, >>, =, etc.
10
11. Overloading Operator* as Non-Friend Function
class Rational { Binary operator has
int num; 2 parameters.
int den;
public:
int main() {
Rational (int num = 0, int den = 1) Rational r1(1,2),
: num(num), den(den) {} r2(1,3),
void print() const { r3(5,6),
cout << num << "/" << den << endl; r4;
r4 = r1 * r2 * r3;
}
r1.print();
int getNum() const { return num; }
r2.print();
int getDen() const { return den; }
r3.print();
}; r4.print();
Rational operator* (const Rational& r1, }
const Rational& r2) {
int n = r1.getNum() * r2.getNum(); Output:
1/2
int d = r1.getDen() * r2.getDen();
1/3
return Rational (n, d); // Return a new 5/6
// Rational object 5/36
}
11
12. Overloading Operator* as Friend Function
class Rational { Binary operator has 2
friend Rational operator* (const Rational&, parameters.
const Rational&);
int num; int main() {
int den; Rational r1(1,2),
public: r2(1,3),
Rational (int num=0, int den=1) r3(5,6),
: num(num), den(den) {} r4;
r4 = r1 * r2 * r3;
void print() const {
r1.print();
cout << num << "/" r2.print();
<< den << endl; r3.print();
} r4.print();
}; }
Rational operator* (const Rational& r1,
Output:
const Rational& r2) { 1/2
int n = r1.num * r2.num; 1/3
int d = r1.den * r2.den; 5/6
return Rational (n, d); // Return a new 5/36
// Rational object
} 12
14. The Increment Operator (‘++’)
Is a unary operator that can be used as both a prefix ( ++x)
and postfix (x++) operator.
If we have overloaded both prefix and postfix versions of the
increment operator for class Rational:
• A prefix call to operator (++x) will generate a call to:
Rational::operator++() // prefix
• A postfix call to operator (x++) will generate a call to:
Rational::operator++(int) // postfix
Postfix requires 1 int parameter to differentiate itself from
prefix.
14
15. Overloading Operator<
Binary operator has 2 parameters.
class Rational {
...
};
bool operator< (const Rational& r1, const Rational&
r2) {
return r1.getNum() * r2.getDen() <
r1.getDen() * r2.getNum();
}
int main() {
Rational r1(1,2), r2(2,3), r3(1,2);
if (r1 < r2) cout << "r1 is smaller than r2n";
else cout << "r1 is NOT smaller than r2n";
if (r1 < r3) cout << "r1 is smaller than r3n";
else cout << "r1 is NOT smaller than r3n";
}
Output:
r1 is smaller than r2
r1 is NOT smaller than r3 15
16. Overloading Operator()
To sort an array or vector of your class by different attribute at
different time.
int main() {
class Point {
Point pts[3] =
int x, y; {Point(3,6),
public: Point(5,4),
Point (int x = 0, int y = 0) : x(x), y(y) { } Point(1,2)};
int getX() const { return x; } for (int i=0; i<3; i++)
cout << pts[i] << " ";
int getY() const { return y; }
cout << endl;
}; sort (pts, pts+3,
ostream& operator<< (ostream& os, const Point& p) { SortByX());
os << "(" << p.getX() << ", " << p.getY() << ")"; for (int i=0; i<3; i++)
return os; cout << pts[i] << " ";
cout << endl;
}
sort (pts, pts+3,
struct SortByX { SortByY());
bool operator() (const Point& p1, const Point& p2) for (int i=0; i<3; i++)
{ return p1.getX() < p2.getX(); } cout << pts[i] << " ";
}; }
struct SortByY {
Output:
bool operator() (const Point& p1, const Point& p2) (3, 6) (5, 4) (1, 2)
{ return p1.getY() < p2.getY(); } (1, 2) (3, 6) (5, 4)
}; (1, 2) (5, 4) (3, 6)
16
17. Exception Handling
When a program is executed, unexpected situations may
occur. Such situations are called exceptions.
In other word: An exception is a runtime error caused by
some abnormal conditions.
Example:
• Division by zero
• Failure of new operator to obtain a requested amount of
memory
Exception handler is code that handles the exception
(runtime error) when it occurs.
17
18. Exception Example: Division By Zero
How to deal with the error below?
double divide (double x, double y) {
return x / y; // divide by 0 if y = 0
}
int main() {
double x, y;
cin >> x >> y;
cout << "Result = " << divide (x, y);
}
18
19. Exception Example: Division By Zero
A solution is shown below. It works but the codes that
handles the error mixes with the codes for division, making
the codes harder to read (is if for division and else for
error handling, or the other way? No direct indication from
if/else keywords alone.
double divide (double x, double y) {
return x / y; // divide by 0 if y = 0
}
int main() {
double x, y;
cin >> x >> y;
if (y == 0) cout << "Cannot divide by zeron";
else cout << "Result = " << divide (x, y);
}
19
20. Exception Handling
C++ implements exception handling using try, throw and
catch block.
try block:
• Write the code that might generate runtime error within
the try block.
try {
// Code that may generate exceptions.
...
if (<error condition is true>)
throw <Exception object>;
...
}
catch (<Exception type>) {
// Error handling code.
...
} 20
21. try, throw, and catch blocks
throw statement:
• Use keyword throw in try block to signal that
abnormal condition or error has occurred.
• If the throw statement is executed, the C++ runtime will
skip the remaining of the try block, and jump to the
catch block to continue execution.
try {
// Code that may generate exceptions.
...
if (<error condition is true>)
throw <Exception object>; // Jump to catch block.
... // Will be skipped if throw statement is executed.
}
catch (<Exception type>) {
// Error handling code.
...
}
21
22. try, throw, and catch blocks
catch block:
• Write the code that catches the thrown exception object
in catch block. This is the exception handler.
• Unhandled/Uncaught thrown exception will terminate the
program.
try {
// Code that may generate exceptions.
...
if (<error condition is true>)
throw <Exception object>;
...
}
// No code here.
catch (<Exception type>) { // Thrown exception object must
// match caught exception type.
// Error handling code.
...
}
22
23. Example: try, throw, and catch blocks
double divide (double x, double y) {
if (y == 0) If there is an exception,
throw y; throw it.
return x / y;
} Put code that may
int main() { generate error in
double x, y; try block.
cin >> x >> y;
try {
If there is no exception,
double result = divide (x, y);
cout << "Result = " << result; resume execution.
}
catch (double a) { If there is an exception
cout << "Cannot divide by zeron"; of type double,
} catch it.
}
23
24. Example: try, throw, and catch blocks
double divide (double x, double y) { Output1:No exception
if (y == 0) 1 2
throw y; Result = 0.5
return x / y;
}
int main() { Output2:With exception
double x, y; 1 0
cin >> x >> y; Cannot divide by zero
try {
double result = divide (x, y);
cout << "Result = " << result;
}
catch (double a) { When an exception is
cout << "Cannot divide by zeron"; thrown, the codes
} that appear after the
} throw statement in
the try block is
skipped.
24
25. Example: try, throw, and catch blocks
double divide (double x, double y) { Output1:No exception
if (y == 0) 1 2
throw y; Result = 0.5
return x / y;
}
int main() { Output2:With exception
double x, y; 1 0
cin >> x >> y; Cannot divide by zero
try {
double result = divide (x, y);
cout << "Result = " << result;
}
catch (double a) { The type of the object
cout << "Cannot divide by zeron"; being thrown must
} match the type of the
} parameter in the
catch block
25
26. Example: try, throw, and catch blocks
double divide (double x, double y) { Output1:No exception
if (y == 0) 1 2
throw y; Result = 0.5
return x / y;
}
int main() { Output2:With exception
double x, y; 1 0
cin >> x >> y; terminate called after
try { throwing an instance of
double result = divide (x, y); 'double'
cout << "Result = " << result;
}
catch (int a) { If the type of object
cout << "Cannot divide by zeron"; being thrown does
} not match the type of
} the parameter in the
catch block,
26
27. Example: try, throw, and catch blocks
Note that exception handling does not require a function to
work.
int main() {
double x, y;
cin >> x >> y;
try {
if (y == 0)
throw y; Output1:No exception
double result = x / y; 1 2
cout << "Result = " << result;
Result = 0.5
}
catch (double a) {
cout << "Cannot divide by zeron"; Output2:With exception
} 1 0
} Cannot divide by zero
27
28. Exception Propagation
If the function containing the throw statement does not
catch the exception, the exception will be propagated up to
the caller of the function until it reaches a try block or the
main function.
In the former case, the try/catch block of the caller
handles the exception if the exception type matches one of
the catch block. Otherwise the exception will be
propagated up again.
If the exception reaches the main function and is not
handled, the program will be terminated.
28
29. Example: Exception Propagation
double f2(double x, double y) { Output:With exception
if (y == 0) throw y;
return x / y; 1 0
} Cannot divide by zero
double f1(double x, double y) {
return f2(x, y);
} The exception is
double divide (double x, double y) { propagated in the
return f1(x, y); following order:
} f2(), f1(),
int main() { divide(),
... main().
try {
double result = divide (x, y); The main() catches
cout << "Result = " << result;
and handles the
}
catch (double a) { exception.
...
29
30. Multiple catch Blocks
Sometimes, we might have many different exceptions
for a small block of code.
try {
...
if (<Error1>) throw <Object of exception type1>;
if (<Error2>) throw <Object of exception type2>;
if (<Error3>) throw <Object of exception type3>;
...
}
catch (<Exception type1>) {
// Code that resolves a type1 exception.
}
catch (<Exception type2>) {
// Code that resolves a type2 exception.
}
catch (<Exception type3>) {
// Code that resolves a typeN exception.
}
30
31. Multiple catch Blocks
But, which catch block will be instigated/invoked?
Depend on the type of exception object.
The type must match exactly, no implicit conversion will
be done by C++. Type double does not match with type
int.
Only one catch block will be executed for an exception.
The catch block that first matches the exception type
would be chosen.
31
32. Multiple catch Blocks
void func (int n) { int main () {
try { func (1);
if (n == 1) throw 11; // int func (3);
if (n == 3) throw 3.5; // double func (4);
cout << "n is not 1 or 3n"; }
}
catch (double a) { // Won't catch int Output:
cout << "Catch double " << a << endl; Catch int 11
} Catch double 3.5
catch (int a) { // Match int n is not 1 or 3
cout << "Catch int " << a << endl;
}
}
No implicit
conversion of
exception type in
catch argument
32
33. Exception Matching
To catch every possible exception type, use ellipsis "…".
try {
...
}
catch (...) { // catches ALL exception types.
...
}
Limitations of catch (...):
• You can't tell what type of exception occurred.
• No argument to reference.
• Should always be placed as the last catch block.
33
34. Exception Matching
void func (int n) { int main () {
try { func (1);
if (n == 1) throw 11; // int func (2);
if (n == 2) throw string("abc"); func (3);
if (n == 3) throw 3.5; // double func (4);
cout << "n is not 1, 2 or 3n"; }
}
catch (double a) {
cout << "Catch double " << a << endl; Output:
} Not double nor string
catch (string a) { Catch string abc
cout << "Catch string " << a << endl; Catch double 3.5
} n is not 1, 2 or 3
catch (...) { // all types
cout << "Not double nor stringn";
}
}
34
35. Advantages of Exception Handling
Using try, throw, and catch blocks to handle
exception offer the following advantages:
1. Provide clarify on the section of codes that
handle the error.
2. You may throw an exception in a
function/method, and handle it somewhere else.
35