本文档基于 exceptions.cpp 文件,详细介绍 C++ 中的异常处理机制,包括自定义异常、标准异常、异常捕获与处理等内容。
异常处理基础 异常处理是 C++ 中一种处理错误的机制,它允许程序在遇到错误时跳转到特定的错误处理代码。
基本异常处理结构 1 2 3 4 5 try { } catch (异常类型 e) { }
自定义异常类 1. 自定义异常基类 1 2 3 4 5 6 7 8 9 10 11 class MyException : public std::exception {private : std::string message; public : MyException (const std::string& msg) : message (msg) {} const char * what () const noexcept override { return message.c_str (); } };
2. 特定异常类 1 2 3 4 5 6 7 8 9 10 11 class DivisionByZeroException : public std::runtime_error {public : DivisionByZeroException () : std::runtime_error ("Division by zero!" ) {} }; class NegativeValueException : public std::runtime_error {public : NegativeValueException (const std::string& msg) : std::runtime_error (msg) {} };
异常抛出与捕获 1. 除法操作异常 1 2 3 4 5 6 double divide (double a, double b) { if (b == 0 ) { throw DivisionByZeroException (); } return a / b; }
2. 平方根计算异常 1 2 3 4 5 6 double squareRoot (double x) { if (x < 0 ) { throw NegativeValueException ("Cannot calculate square root of negative number" ); } return std::sqrt (x); }
3. 值处理异常 1 2 3 4 5 6 7 8 9 void processValue (int value) { if (value < 0 ) { throw MyException ("Value cannot be negative" ); } if (value > 100 ) { throw std::out_of_range ("Value exceeds maximum limit of 100" ); } std::cout << "Processing value: " << value << std::endl; }
4. 向量元素访问异常 1 2 3 4 5 6 int getElement (const std::vector<int >& vec, int index) { if (index < 0 || index >= vec.size ()) { throw std::out_of_range ("Index out of range" ); } return vec[index]; }
异常处理示例 1. 基本异常处理 1 2 3 4 5 6 7 8 std::cout << "=== Basic Exception Handling ===" << std::endl; try { int divisor = 0 ; int result = 10 / divisor; std::cout << "Result: " << result << std::endl; } catch (const std::exception& e) { std::cout << "Caught exception: " << e.what () << std::endl; }
2. 自定义异常处理 1 2 3 4 5 6 7 8 9 10 11 12 std::cout << "\n=== Custom Exception ===" << std::endl; try { processValue (-5 ); } catch (const MyException& e) { std::cout << "Caught MyException: " << e.what () << std::endl; } try { processValue (150 ); } catch (const std::out_of_range& e) { std::cout << "Caught out_of_range: " << e.what () << std::endl; }
3. 除法异常处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 std::cout << "\n=== Division Exception ===" << std::endl; try { double result = divide (10.0 , 0.0 ); std::cout << "Result: " << result << std::endl; } catch (const DivisionByZeroException& e) { std::cout << "Caught DivisionByZeroException: " << e.what () << std::endl; } try { double result = divide (10.0 , 2.0 ); std::cout << "Result: " << result << std::endl; } catch (const DivisionByZeroException& e) { std::cout << "Caught DivisionByZeroException: " << e.what () << std::endl; }
4. 平方根异常处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 std::cout << "\n=== Square Root Exception ===" << std::endl; try { double result = squareRoot (-4 ); std::cout << "Result: " << result << std::endl; } catch (const NegativeValueException& e) { std::cout << "Caught NegativeValueException: " << e.what () << std::endl; } try { double result = squareRoot (16 ); std::cout << "Result: " << result << std::endl; } catch (const NegativeValueException& e) { std::cout << "Caught NegativeValueException: " << e.what () << std::endl; }
5. 多个 catch 块 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 std::cout << "\n=== Multiple Catch Blocks ===" << std::endl; try { int choice = 1 ; if (choice == 1 ) { throw std::runtime_error ("Runtime error occurred" ); } else if (choice == 2 ) { throw std::logic_error ("Logic error occurred" ); } else { throw std::exception (); } } catch (const std::runtime_error& e) { std::cout << "Caught runtime_error: " << e.what () << std::endl; } catch (const std::logic_error& e) { std::cout << "Caught logic_error: " << e.what () << std::endl; } catch (const std::exception& e) { std::cout << "Caught generic exception: " << e.what () << std::endl; }
6. 嵌套 try-catch 1 2 3 4 5 6 7 8 9 10 11 std::cout << "\n=== Nested Try-Catch ===" << std::endl; try { try { throw std::runtime_error ("Inner exception" ); } catch (const std::exception& e) { std::cout << "Inner catch: " << e.what () << std::endl; throw std::runtime_error ("Outer exception" ); } } catch (const std::exception& e) { std::cout << "Outer catch: " << e.what () << std::endl; }
7. 向量索引异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 std::cout << "\n=== Vector Index Exception ===" << std::endl; std::vector<int > numbers = {10 , 20 , 30 , 40 , 50 }; try { int value = getElement (numbers, 2 ); std::cout << "Element at index 2: " << value << std::endl; } catch (const std::out_of_range& e) { std::cout << "Caught out_of_range: " << e.what () << std::endl; } try { int value = getElement (numbers, 10 ); std::cout << "Element at index 10: " << value << std::endl; } catch (const std::out_of_range& e) { std::cout << "Caught out_of_range: " << e.what () << std::endl; }
8. 捕获所有异常 1 2 3 4 5 6 7 8 std::cout << "\n=== Catch All Exceptions ===" << std::endl; try { riskyFunction (); } catch (const std::exception& e) { std::cout << "Caught exception: " << e.what () << std::endl; } catch (...) { std::cout << "Caught unknown exception" << std::endl; }
9. 无异常保证 1 2 3 4 5 6 7 std::cout << "\n=== No-throw Guarantee ===" << std::endl; auto safeDivide = [](double a, double b) noexcept { return (b != 0 ) ? a / b : 0 ; }; double result = safeDivide (10.0 , 0.0 );std::cout << "Safe division result: " << result << std::endl;
10. 异常规格说明 1 2 3 4 5 6 7 8 9 10 std::cout << "\n=== Exception Specification ===" << std::endl; auto functionWithExceptionSpec = []() throw (std::runtime_error) { throw std::runtime_error ("Specified exception" ); }; try { functionWithExceptionSpec (); } catch (const std::runtime_error& e) { std::cout << "Caught specified exception: " << e.what () << std::endl; }
11. 重新抛出异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 std::cout << "\n=== Rethrowing Exception ===" << std::endl; auto processAndRethrow = []() { try { throw std::runtime_error ("Original exception" ); } catch (const std::exception& e) { std::cout << "Caught in inner handler: " << e.what () << std::endl; throw ; } }; try { processAndRethrow (); } catch (const std::exception& e) { std::cout << "Caught in outer handler: " << e.what () << std::endl; }
12. 标准异常 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 std::cout << "\n=== Standard Exceptions ===" << std::endl; try { throw std::invalid_argument ("Invalid argument provided" ); } catch (const std::invalid_argument& e) { std::cout << "Caught invalid_argument: " << e.what () << std::endl; } try { throw std::length_error ("Length error occurred" ); } catch (const std::length_error& e) { std::cout << "Caught length_error: " << e.what () << std::endl; } try { throw std::bad_alloc (); } catch (const std::bad_alloc& e) { std::cout << "Caught bad_alloc: " << e.what () << std::endl; }
13. 构造函数中的异常 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 std::cout << "\n=== Exception in Constructor ===" << std::endl; class Resource {public : Resource (int size) { if (size <= 0 ) { throw std::invalid_argument ("Size must be positive" ); } std::cout << "Resource created with size: " << size << std::endl; } ~Resource () { std::cout << "Resource destroyed" << std::endl; } }; try { Resource res (10 ) ; } catch (const std::exception& e) { std::cout << "Exception in constructor: " << e.what () << std::endl; } try { Resource res (-5 ) ; } catch (const std::exception& e) { std::cout << "Exception in constructor: " << e.what () << std::endl; }
异常处理最佳实践
只在真正异常的情况下使用异常 :不要将异常用于常规控制流
抛出有意义的异常 :异常信息应该清晰地描述错误原因
捕获合适的异常类型 :尽量捕获具体的异常类型,而不是所有异常
使用 RAII 管理资源 :确保即使发生异常,资源也能被正确释放
考虑异常安全性 :编写代码时考虑异常可能带来的影响
编译说明 使用以下命令编译本文档中的示例代码,确保中文输出正常:
1 g++ -fexec-charset=GBK exceptions.cpp -o exceptions.exe
-fexec-charset=GBK 选项确保编译后的程序能够正确输出中文字符。
完整示例代码 以下是完整的示例代码,包含本文档中所有的异常处理示例:
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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 #include <iostream> #include <stdexcept> #include <string> #include <vector> #include <cmath> class MyException : public std::exception {private : std::string message; public : MyException (const std::string& msg) : message (msg) {} const char * what () const noexcept override { return message.c_str (); } }; class DivisionByZeroException : public std::runtime_error {public : DivisionByZeroException () : std::runtime_error ("Division by zero!" ) {} }; class NegativeValueException : public std::runtime_error {public : NegativeValueException (const std::string& msg) : std::runtime_error (msg) {} }; double divide (double a, double b) { if (b == 0 ) { throw DivisionByZeroException (); } return a / b; } double squareRoot (double x) { if (x < 0 ) { throw NegativeValueException ("Cannot calculate square root of negative number" ); } return std::sqrt (x); } void processValue (int value) { if (value < 0 ) { throw MyException ("Value cannot be negative" ); } if (value > 100 ) { throw std::out_of_range ("Value exceeds maximum limit of 100" ); } std::cout << "Processing value: " << value << std::endl; } int getElement (const std::vector<int >& vec, int index) { if (index < 0 || index >= vec.size ()) { throw std::out_of_range ("Index out of range" ); } return vec[index]; } void riskyFunction () { throw std::runtime_error ("Something went wrong in riskyFunction!" ); } int main () { std::cout << "=== Basic Exception Handling ===" << std::endl; try { int divisor = 0 ; int result = 10 / divisor; std::cout << "Result: " << result << std::endl; } catch (const std::exception& e) { std::cout << "Caught exception: " << e.what () << std::endl; } std::cout << "\n=== Custom Exception ===" << std::endl; try { processValue (-5 ); } catch (const MyException& e) { std::cout << "Caught MyException: " << e.what () << std::endl; } try { processValue (150 ); } catch (const std::out_of_range& e) { std::cout << "Caught out_of_range: " << e.what () << std::endl; } std::cout << "\n=== Division Exception ===" << std::endl; try { double result = divide (10.0 , 0.0 ); std::cout << "Result: " << result << std::endl; } catch (const DivisionByZeroException& e) { std::cout << "Caught DivisionByZeroException: " << e.what () << std::endl; } try { double result = divide (10.0 , 2.0 ); std::cout << "Result: " << result << std::endl; } catch (const DivisionByZeroException& e) { std::cout << "Caught DivisionByZeroException: " << e.what () << std::endl; } std::cout << "\n=== Square Root Exception ===" << std::endl; try { double result = squareRoot (-4 ); std::cout << "Result: " << result << std::endl; } catch (const NegativeValueException& e) { std::cout << "Caught NegativeValueException: " << e.what () << std::endl; } try { double result = squareRoot (16 ); std::cout << "Result: " << result << std::endl; } catch (const NegativeValueException& e) { std::cout << "Caught NegativeValueException: " << e.what () << std::endl; } std::cout << "\n=== Multiple Catch Blocks ===" << std::endl; try { int choice = 1 ; if (choice == 1 ) { throw std::runtime_error ("Runtime error occurred" ); } else if (choice == 2 ) { throw std::logic_error ("Logic error occurred" ); } else { throw std::exception (); } } catch (const std::runtime_error& e) { std::cout << "Caught runtime_error: " << e.what () << std::endl; } catch (const std::logic_error& e) { std::cout << "Caught logic_error: " << e.what () << std::endl; } catch (const std::exception& e) { std::cout << "Caught generic exception: " << e.what () << std::endl; } std::cout << "\n=== Nested Try-Catch ===" << std::endl; try { try { throw std::runtime_error ("Inner exception" ); } catch (const std::exception& e) { std::cout << "Inner catch: " << e.what () << std::endl; throw std::runtime_error ("Outer exception" ); } } catch (const std::exception& e) { std::cout << "Outer catch: " << e.what () << std::endl; } std::cout << "\n=== Vector Index Exception ===" << std::endl; std::vector<int > numbers = {10 , 20 , 30 , 40 , 50 }; try { int value = getElement (numbers, 2 ); std::cout << "Element at index 2: " << value << std::endl; } catch (const std::out_of_range& e) { std::cout << "Caught out_of_range: " << e.what () << std::endl; } try { int value = getElement (numbers, 10 ); std::cout << "Element at index 10: " << value << std::endl; } catch (const std::out_of_range& e) { std::cout << "Caught out_of_range: " << e.what () << std::endl; } std::cout << "\n=== Catch All Exceptions ===" << std::endl; try { riskyFunction (); } catch (const std::exception& e) { std::cout << "Caught exception: " << e.what () << std::endl; } catch (...) { std::cout << "Caught unknown exception" << std::endl; } std::cout << "\n=== No-throw Guarantee ===" << std::endl; auto safeDivide = [](double a, double b) noexcept { return (b != 0 ) ? a / b : 0 ; }; double result = safeDivide (10.0 , 0.0 ); std::cout << "Safe division result: " << result << std::endl; std::cout << "\n=== Exception Specification ===" << std::endl; auto functionWithExceptionSpec = []() throw (std::runtime_error) { throw std::runtime_error ("Specified exception" ); }; try { functionWithExceptionSpec (); } catch (const std::runtime_error& e) { std::cout << "Caught specified exception: " << e.what () << std::endl; } std::cout << "\n=== Rethrowing Exception ===" << std::endl; auto processAndRethrow = []() { try { throw std::runtime_error ("Original exception" ); } catch (const std::exception& e) { std::cout << "Caught in inner handler: " << e.what () << std::endl; throw ; } }; try { processAndRethrow (); } catch (const std::exception& e) { std::cout << "Caught in outer handler: " << e.what () << std::endl; } std::cout << "\n=== Standard Exceptions ===" << std::endl; try { throw std::invalid_argument ("Invalid argument provided" ); } catch (const std::invalid_argument& e) { std::cout << "Caught invalid_argument: " << e.what () << std::endl; } try { throw std::length_error ("Length error occurred" ); } catch (const std::length_error& e) { std::cout << "Caught length_error: " << e.what () << std::endl; } try { throw std::bad_alloc (); } catch (const std::bad_alloc& e) { std::cout << "Caught bad_alloc: " << e.what () << std::endl; } std::cout << "\n=== Exception in Constructor ===" << std::endl; class Resource { public : Resource (int size) { if (size <= 0 ) { throw std::invalid_argument ("Size must be positive" ); } std::cout << "Resource created with size: " << size << std::endl; } ~Resource () { std::cout << "Resource destroyed" << std::endl; } }; try { Resource res (10 ) ; } catch (const std::exception& e) { std::cout << "Exception in constructor: " << e.what () << std::endl; } try { Resource res (-5 ) ; } catch (const std::exception& e) { std::cout << "Exception in constructor: " << e.what () << std::endl; } return 0 ; }
总结 异常处理是 C++ 中一种强大的错误处理机制,它允许程序在遇到错误时能够优雅地处理并恢复。通过本文档的学习,您应该已经掌握了以下内容:
基本异常处理结构
自定义异常类的创建和使用
各种类型异常的捕获和处理
异常处理的最佳实践
如何确保中文输出正常
合理使用异常处理可以使您的代码更加健壮、可读性更高,并且能够更好地处理各种错误情况。
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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 ## exceptions.cpp ```c++ #include <iostream> #include <stdexcept> #include <string> #include <vector> #include <cmath> class MyException : public std::exception { private: std::string message; public: MyException(const std::string& msg) : message(msg) {} const char* what() const noexcept override { return message.c_str(); } }; class DivisionByZeroException : public std::runtime_error { public: DivisionByZeroException() : std::runtime_error("Division by zero!") {} }; class NegativeValueException : public std::runtime_error { public: NegativeValueException(const std::string& msg) : std::runtime_error(msg) {} }; double divide(double a, double b) { if (b == 0) { throw DivisionByZeroException(); } return a / b; } double squareRoot(double x) { if (x < 0) { throw NegativeValueException("Cannot calculate square root of negative number"); } return std::sqrt(x); } void processValue(int value) { if (value < 0) { throw MyException("Value cannot be negative"); } if (value > 100) { throw std::out_of_range("Value exceeds maximum limit of 100"); } std::cout << "Processing value: " << value << std::endl; } int getElement(const std::vector<int>& vec, int index) { if (index < 0 || index >= vec.size()) { throw std::out_of_range("Index out of range"); } return vec[index]; } void riskyFunction() { throw std::runtime_error("Something went wrong in riskyFunction!"); } int main() { std::cout << "=== Basic Exception Handling ===" << std::endl; try { double divisor = 0.0; double result = divide(10.0, divisor); std::cout << "Result: " << result << std::endl; } catch (const std::exception& e) { std::cout << "Caught exception: " << e.what() << std::endl; } std::cout << "\n=== Custom Exception ===" << std::endl; try { processValue(-5); } catch (const MyException& e) { std::cout << "Caught MyException: " << e.what() << std::endl; } try { processValue(150); } catch (const std::out_of_range& e) { std::cout << "Caught out_of_range: " << e.what() << std::endl; } std::cout << "\n=== Division Exception ===" << std::endl; try { double result = divide(10.0, 0.0); std::cout << "Result: " << result << std::endl; } catch (const DivisionByZeroException& e) { std::cout << "Caught DivisionByZeroException: " << e.what() << std::endl; } try { double result = divide(10.0, 2.0); std::cout << "Result: " << result << std::endl; } catch (const DivisionByZeroException& e) { std::cout << "Caught DivisionByZeroException: " << e.what() << std::endl; } std::cout << "\n=== Square Root Exception ===" << std::endl; try { double result = squareRoot(-4); std::cout << "Result: " << result << std::endl; } catch (const NegativeValueException& e) { std::cout << "Caught NegativeValueException: " << e.what() << std::endl; } try { double result = squareRoot(16); std::cout << "Result: " << result << std::endl; } catch (const NegativeValueException& e) { std::cout << "Caught NegativeValueException: " << e.what() << std::endl; } std::cout << "\n=== Multiple Catch Blocks ===" << std::endl; try { int choice = 1; if (choice == 1) { throw std::runtime_error("Runtime error occurred"); } else if (choice == 2) { throw std::logic_error("Logic error occurred"); } else { throw std::exception(); } } catch (const std::runtime_error& e) { std::cout << "Caught runtime_error: " << e.what() << std::endl; } catch (const std::logic_error& e) { std::cout << "Caught logic_error: " << e.what() << std::endl; } catch (const std::exception& e) { std::cout << "Caught generic exception: " << e.what() << std::endl; } std::cout << "\n=== Nested Try-Catch ===" << std::endl; try { try { throw std::runtime_error("Inner exception"); } catch (const std::exception& e) { std::cout << "Inner catch: " << e.what() << std::endl; throw std::runtime_error("Outer exception"); } } catch (const std::exception& e) { std::cout << "Outer catch: " << e.what() << std::endl; } std::cout << "\n=== Vector Index Exception ===" << std::endl; std::vector<int> numbers = {10, 20, 30, 40, 50}; try { int value = getElement(numbers, 2); std::cout << "Element at index 2: " << value << std::endl; } catch (const std::out_of_range& e) { std::cout << "Caught out_of_range: " << e.what() << std::endl; } try { int value = getElement(numbers, 10); std::cout << "Element at index 10: " << value << std::endl; } catch (const std::out_of_range& e) { std::cout << "Caught out_of_range: " << e.what() << std::endl; } std::cout << "\n=== Catch All Exceptions ===" << std::endl; try { riskyFunction(); } catch (const std::exception& e) { std::cout << "Caught exception: " << e.what() << std::endl; } catch (...) { std::cout << "Caught unknown exception" << std::endl; } std::cout << "\n=== No-throw Guarantee ===" << std::endl; auto safeDivide = [](double a, double b) noexcept { return (b != 0) ? a / b : 0; }; double result = safeDivide(10.0, 0.0); std::cout << "Safe division result: " << result << std::endl; std::cout << "\n=== Exception Specification ===" << std::endl; auto functionWithExceptionSpec = []() { throw std::runtime_error("Specified exception"); }; try { functionWithExceptionSpec(); } catch (const std::runtime_error& e) { std::cout << "Caught specified exception: " << e.what() << std::endl; } std::cout << "\n=== Rethrowing Exception ===" << std::endl; auto processAndRethrow = []() { try { throw std::runtime_error("Original exception"); } catch (const std::exception& e) { std::cout << "Caught in inner handler: " << e.what() << std::endl; throw; } }; try { processAndRethrow(); } catch (const std::exception& e) { std::cout << "Caught in outer handler: " << e.what() << std::endl; } std::cout << "\n=== Standard Exceptions ===" << std::endl; try { throw std::invalid_argument("Invalid argument provided"); } catch (const std::invalid_argument& e) { std::cout << "Caught invalid_argument: " << e.what() << std::endl; } try { throw std::length_error("Length error occurred"); } catch (const std::length_error& e) { std::cout << "Caught length_error: " << e.what() << std::endl; } try { throw std::bad_alloc(); } catch (const std::bad_alloc& e) { std::cout << "Caught bad_alloc: " << e.what() << std::endl; } std::cout << "\n=== Exception in Constructor ===" << std::endl; class Resource { public: Resource(int size) { if (size <= 0) { throw std::invalid_argument("Size must be positive"); } std::cout << "Resource created with size: " << size << std::endl; } ~Resource() { std::cout << "Resource destroyed" << std::endl; } }; try { Resource res(10); } catch (const std::exception& e) { std::cout << "Exception in constructor: " << e.what() << std::endl; } try { Resource res(-5); } catch (const std::exception& e) { std::cout << "Exception in constructor: " << e.what() << std::endl; } return 0; }