-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexceptions_catch.cpp
More file actions
177 lines (162 loc) · 5.09 KB
/
Copy pathexceptions_catch.cpp
File metadata and controls
177 lines (162 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// #define NDEBUG
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstddef> // for std::size_t
#include <exception> // for std::exception
#include <limits>
#include <string> // for this example
#include <stdexcept>
void function1(int x)
{
if(x < 0)
throw -1;
else
std::cout << x << '\n';
}
class DummyException // An exception type that will never be hit (can't be instantiated)
{
DummyException() = delete;
};
class ArrayExceptions
{
private:
std::string m_error{};
public:
explicit ArrayExceptions(std::string_view error)
: m_error{static_cast<std::string>(error)}
{}
std::string_view getError() const { return m_error; }
};
class ArrayExceptionsR: public std::runtime_error // we derived from the derived class of std::exception
{
public:
explicit ArrayExceptionsR(const std::string& error)
: std::runtime_error{error}
{}
// No need for get() or what() anymore
};
class IntArray
{
private:
int m_array[5]{};
int m_length{};
public:
IntArray() = default;
explicit IntArray(std::initializer_list<int> list) // when exception takes place here, all the member variables which has been initialized will be distructed
: m_length{static_cast<int>(list.size())} // the construction will be terminated, the members with RAII strategy will be fine.
{
if(list.size() > 5)
throw ArrayExceptionsR{"Overwhelming allocation"}; // if we use const char* directly here to identify what caused the exceptions
std::copy_n(list.begin(), list.size(), m_array); // we could only get ONE solution by catch(const char*)
} // which is Inflexible
int& operator[](int index)
{
if(index < 0 || index >= m_length)
throw ArrayExceptionsR{"Invalid index"};
return m_array[index];
}
};
class A
{
private:
int m_x;
public:
A(int x) : m_x{x}
{
if (x <= 0)
throw 1; // Exception thrown here
}
};
class B : public A
{
public:
B(int x) try : A{x} // note addition of try keyword here
{
}
catch (...) // note this is at same level of indentation as the function itself
{
// Exceptions from member initializer list or
// from constructor body are caught here
std::cerr << "Exception caught in class\n";
throw; // rethrow the existing exception
}
};
int main()
{
// One
try
{
function1(6);
}
#ifdef NDEBUG // if we are in Release Mode, we need catch-all handler for Clean the program when the exception was not caught
catch(...) // match every exception to handle it. aka Last line of defense
{
std::cerr << "Abnormal termination\n";
}
#else // if we are debugging, we don't want the exception hit the catch and Make Clean to the program which will lose all the informations we need to solve the problem
catch(DummyException) // a try requires at least a catch but we don't want this catch to match any exceptions, so we just make a mission impossible for matching
{
}
#endif
// Two
try
{
IntArray arr{1, 2, 3, 4, 5};
int value{arr[4]};
std::cout << "value: " << value << '\n';
}
catch(const ArrayExceptions& error) // all kinds of Error in class ArrayError can be handled here, instead of One solution matched with a string
{
std::cerr << "An array exception occured (" << error.getError() << ")\n";
}
// Three
try
{
std::string s;
s.resize(std::numeric_limits<std::size_t>::max()); // detect standard exceptions here
}
// One of std::exception's Derived class
catch(const std::length_error& length_errpr) // take care std::lengtherror (one derived of standard exceptions) here
{
std::cerr << "You ran out of memory!" << '\n';
}
// the Deriveds can be taken over by the Base catch
catch(const std::exception& e) // std::exception is a Base class (interface class), we will handle all the standard exceptions here if the exception didn't be take care berfore
{
std::cerr << "Standard exception: " << e.what() << '\n'; // what() is a virtual function
}
// Four
try
{
throw std::runtime_error("Bad things happened"); // you can throw std::exception (Derived class, not itself) manually
}
// This handler will catch std::exception and all the derived exceptions too
catch (const std::exception& exception)
{
std::cerr << "Standard exception: " << exception.what() << '\n';
}
// Five
try
{
IntArray arr_1{1, 2, 3, 4, 5, 6};
}
catch (const ArrayExceptionsR& error)
{
std::cerr << error.what() << '\n'; // Inherited from runtime_error
}
catch (const std::exception& exception)
{
std::cerr << "Standard exception: " << exception.what() << '\n';
}
// Six
try
{
B b{0};
}
catch (int)
{
std::cout << "Oops\n";
}
return 0;
}