Exception Handling in C++: Multiple Catches

A try-catch block may contain multiple catch clauses to deal with different Point exceptions thrown in the try clause.

Usually a try block should run without exceptions. Occasionally, though, it may throw an exception of one type or another. For example, a nonpositive value for a side in a triangle in Listing 16.11 may be considered a type of exception different from a TriangleException. So, the try block may throw a nonpositive-side exception or a TriangleException, depending on the occasion. One catch block can catch only one type of exception. C++ allows you to add multiple catch blocks after a try block in order to catch multiple types of exceptions.

Let us revise the example in the preceding section by creating a new exception class named NonPositiveSideException and incorporating it in the Triangle class. The NonPositiveSideException class is shown in Listing 16.12 and the new Triangle class in Listing 16.13.

Listing 16.12 NonPositiveSideException.h

1 #ifndef NonPositiveSideException_H
2
#define NonPositiveSideException_H
3
#include <stdexcept>
4
using namespace std;
5
6
class NonPositiveSideException: public logic_error
7 {
8     
public:
9      NonPositiveSideException(
double side)
10     : logic_error(
“Non-positive side”)
11    {
12       
this->side = side;
13    }
14
15   
double getSide()
16    {
17       
return side;
18    }
19
20   
private:
21   
double side;
22 };
23
24
#endif

The NonPositiveSideException class describes a logic error, so it is appropriate to define this class to extend the standard logic_error class in line 6.

Listing 16.13 NewTriangle.h

1 #ifndef TRIANGLE_H
2
#define TRIANGLE_H
3
#include “AbstractGeometricObject.h”
4 #include “TriangleException.h”
5 #include “NonPositiveSideException.h”
6 #include <cmath>
7
8
class Triangle: public GeometricObject
9 {
10
public:
11    Triangle()
12    {
13       side1 = side2 = side3 =
1;
14    }
15
16    Triangle(
double side1, double side2, double side3)
17    {
18        check(side1);
19        check(side2);
20        check(side3);
21
22       
if (!isValid(side1, side2, side3))
23       
throw TriangleException(side1, side2, side3);
24
25       
this->side1 = side1;
26       
this->side2 = side2;
27       
this->side3 = side3;
28    }
29
30   
double getSide1() const
31    {
32       
return side1;
33    }
34
35   
double getSide2() const
36    {
37       
return side2;
38    }
39
40   
double getSide3() const
41    {
42       
return side3;
43    }
44
45   
void setSide1(double side1)
46    {
47        check(side1);
48       
if (!isValid(side1, side2, side3))
49       
throw TriangleException(side1, side2, side3);
50
51       
this->side1 = side1;
52    }
53
54   
void setSide2(double side2)
55    {
56        check(side2);
57       
if (!isValid(side1, side2, side3))

58        throw TriangleException(side1, side2, side3);
59
60       
this->side2 = side2;
61    }
62
63   
void setSide3(double side3)
64    {
65        check(side3);
66       
if (!isValid(side1, side2, side3))
67       
throw TriangleException(side1, side2, side3);
68
69       
this->side3 = side3;
70    }
71
72   
double getPerimeter() const
73    {
74       
return side1 + side2 + side3;
75    }
76
77   
double getArea() const
78    {
79       
double s = getPerimeter() / 2;
80       
return sqrt(s * (s – side1) * (s – side2) * (s – side3));
81     }
82
83
private:
84     
double side1, side2, side3;
85
86     
bool isValid(double side1, double side2, double side3) const
87    {
88       
return (side1 < side2 + side3) && (side2 < side1 + side3) &&
89            (side3 < side1 + side2);
90    }
91
92   
void check(double side) const
93    {
94       
if (side <= 0)
95       
throw NonPositiveSideException(side);
96     }
97 };
98
99
#endif

The new Triangle class is identical to the one in Listing 16.10, except that it also checks nonpositive sides. When a Triangle object is created, all of its sides are checked by invoking the check function (lines 18-20). The check function checks whether a side is nonpositive (line 94); it throws a NonPositiveSideException (line 95).

Listing 16.14 gives a test program that prompts the user to enter three sides (lines 9-11) and creates a Triangle object (line 12).

Listing 16.14 MultipleCatchDemo.cpp

1 #include <iostream>
2
#include “NewTriangle.h”
3 using namespace std;
4
5
int main()
6 {
7   
try

8    {
9       cout <<
“Enter three sides: “;
10     
double side1, side2, side3;
11      cin >> side1 >> side2 >> side3;
12      Triangle triangle(side1, side2, side3);
13      cout <<
“Perimeter is ” << triangle.getPerimeter() << endl;
14      cout <<
“Area is ” << triangle.getArea() << endl;
15    }
16   
catch (NonPositiveSideException& ex)
17    {
18        cout << ex.what();
19        cout <<
” the side is ” << ex.getSide() << endl;
20    }
21   
catch (TriangleException& ex)
22    {
23        cout << ex.what();
24        cout <<
” three sides are ” << ex.getSide1() << ” ”
25        << ex.getSide2() << ” ” << ex.getSide3() << endl;
26    }
27
28   
return 0;
29 }

As shown in the sample output, if you enter three sides 2, 2.5, and 2.5, it is a legal triangle. The program displays the perimeter and area of the triangle (lines 13-14). If you enter -1, 1, and 1, the constructor (line 12) throws a NonPositiveSideException. This exception is caught by the catch block in line 16 and processed in lines 18-19. If you enter 1, 2, and 1, the constructor (line 12) throws a TriangleException. This exception is caught by the catch block in line 21 and processed in lines 23-25.

You may use an ellipsis (…) as the parameter of catch, which will catch any exception no matter what the type of the exception that was thrown. This can be used as a default handler that catches all exceptions not caught by other handlers if it is specified last, as shown in the following example:

try

{

Execute some code here

}

catch (Exception1& exl)

{

cout << “Handle Exception!.” << endl;

}

catch (Exception2& ex2)

{

cout << “Handle Exception2” << endl;

}

catch (…)

{

cout << “Handle all other exceptions” << endl;

}

Source: Liang Y. Daniel (2013), Introduction to programming with C++, Pearson; 3rd edition.

Leave a Reply

Your email address will not be published. Required fields are marked *