C++ 异常处理:Try、Catch、throw 示例
什么是 C++ 中的异常处理?
C++ 中的异常处理为您提供了一种处理意外情况(如运行时错误)的方法。因此,每当发生意外情况时,程序控制就会转移到称为处理程序的特殊功能。
要捕获异常,您可以将某些代码段置于异常检查之下。这段代码放在 try-catch 块中。
如果该段代码中出现异常情况,就会抛出异常。接下来,异常处理程序将接管程序的控制权。
如果没有异常情况发生,代码将正常执行。处理程序将被忽略。
在本 C++ 教程中,您将学习:
- 什么是 C++ 中的异常处理?
- 为什么要进行异常处理?
- 异常处理关键字
- 语法:
- C++ 标准异常
- 用户定义的异常
为什么要处理异常?
以下是在 C++ 中使用异常处理的原因:
- 您需要将错误处理代码与正常代码分开。代码将更具可读性和更易于维护。
- 函数可以处理它们选择的异常。即使一个函数抛出许多异常,它也只会处理一些异常。调用者将处理未捕获的异常。
异常处理关键字
C++ 中的异常处理围绕着这三个关键字展开:
- 投掷 – 当程序遇到问题时,它会抛出异常。 throw 关键字帮助程序执行 throw。
- 赶上 – 程序使用异常处理程序来捕获异常。它被添加到您需要处理问题的程序部分。这是使用 catch 关键字完成的。
- 试试 – try 块标识将激活某些异常的代码块。它后面应该跟一个/多个 catch 块。
假设代码块将引发异常。异常将被使用 try 和 catch 关键字的方法捕获。 try/catch 块应该围绕可能引发异常的代码。这样的代码被称为受保护的代码。
语法:
try/catch 采用这种语法:
try { // the protected code } catch( Exception_Name exception1 ) { // catch block } catch( Exception_Name exception2 ) { // catch block } catch( Exception_Name exceptionN ) { // catch block }
- 虽然我们只有一个 try 语句,但我们可以有多个 catch 语句。
- ExceptionName 是要捕获的异常的名称。
- exception1、exception2 和 exceptionN 是您定义的用于引用异常的名称。
示例 1:
#include<iostream> #include<vector> using namespace std; int main() { vector<int> vec; vec.push_back(0); vec.push_back(1); // access the third element, which doesn't exist try { vec.at(2); } catch (exception& ex) { cout << "Exception occurred!" << endl; } return 0; }
输出:
下面是代码截图:
代码说明:
- 在程序中包含 iostream 头文件以使用其功能。
- 在程序中包含矢量头文件以使用其功能。
- 将程序中的 std 命名空间包含到它的类中而不调用它。
- 调用 main() 函数。程序逻辑应添加到其主体中。
- 创建一个名为 vec 的向量来存储整数数据。
- 将元素 0 添加到名为 vec 的向量中。
- 将元素 1 添加到名为 vec 的向量中。
- 评论。它将被 C++ 编译器跳过。
- 使用 try 语句捕获异常。 { 标记 try/catch 块主体的开始。在正文中添加的代码将成为受保护的代码。
- 尝试访问存储在名为 vec 的向量的索引 2(第三个元素)处的元素。该元素不存在。
- try/catch 块的主体结束。
- 捕捉异常。返回的错误信息将存储在变量 ex 中。
- 如果捕获到异常,则在控制台上打印一些消息。
- catch 块主体的结尾。
- 程序应在成功执行后返回一个值。
- main() 函数体结束。
示例 2:
#include <iostream> using namespace std; double zeroDivision(int x, int y) { if (y == 0) { throw "Division by Zero!"; } return (x / y); } int main() { int a = 11; int b = 0; double c = 0; try { c = zeroDivision(a, b); cout << c << endl; } catch (const char* message) { cerr << message << endl; } return 0; }
输出:
下面是代码截图:
代码说明:
- 在程序中包含 iostream 头文件以使用其功能。
- 将程序中的 std 命名空间包含到它的类中而不调用它。
- 创建一个名为 zeroDivision 的函数,它接受两个整数参数 x 和 y。该函数应返回双精度结果。
- 使用 if 语句检查变量参数 y 的值是否为 0。{ 标记 if 正文的开始。
- y 为 0 时返回/抛出的消息。
- if 语句主体的结尾。
- zeroDivision 函数应返回 x/y 的值。
- zeroDivision 函数主体的结尾。
- 调用 main() 方法。 { 标记此方法的开始。
- 声明一个整型变量并将其赋值为 11。
- 声明一个整数变量 b 并将其赋值为 0。
- 声明一个双变量 c 并将其赋值为 0。
- 使用 try 语句捕获异常。 { 标记 try/catch 块主体的开始。在正文中添加的代码将成为受保护的代码。
- 调用 zeroDivision 函数并传递给参数 a 和 b,即 11 和 0。此操作的结果将存储在变量 c 中。
- 在控制台打印出变量 c 的值。
- try/catch 块的主体结束。
- 捕捉异常。返回的错误信息将存储在变量 message 中。
- 在控制台打印返回的错误信息。
- catch 块主体的结尾。
- 程序应在成功执行后返回一个值。
- main() 函数体结束。
C++ 标准异常
C++ 附带了在
用户定义的异常
C++ std::exception 类允许我们定义可以作为异常抛出的对象。此类已在
此函数返回 char * 类型的以空字符结尾的字符序列。我们可以在派生类中覆盖它以获得异常描述。
示例:
#include <iostream> #include <exception> using namespace std; class newException : public exception { virtual const char* what() const throw() { return "newException occurred"; } } newex; int main() { try { throw newex; } catch (exception& ex) { cout << ex.what() << '\n'; } return 0; }
输出:
下面是代码截图:
代码说明:
- 在我们的程序中包含 iostream 头文件。我们将使用它的功能而不会出错。
- 在我们的程序中包含异常头文件。我们将使用它的功能,就像没有错误一样。
- 在我们的程序中包含 std 命名空间以使用它的类而不调用它。
- 创建一个名为 newException 的新类。这个类继承了C++的异常类。
- 类主体的开头。
- 覆盖异常头文件中定义的虚成员函数what()。然后我们将描述我们自己的异常,即新异常。
- 开始新异常的定义。
- 捕获到新异常时返回的消息。
- 新异常的定义结束。
- 类 newException 的主体结束。 newex 是用于捕获新异常的名称,之后将调用 newException。
- 调用 main() 函数。程序逻辑应添加到其主体中。 { 标志着它的主体的开始。
- 使用 try 语句来标记我们需要在其中标记异常的代码。 { 标记 try/catch 块主体的开始。被它包围的代码将受到保护。
- 如果捕获到 newex 异常,则抛出它。
- try 正文结束。
- 使用 catch 语句捕获异常。异常错误消息将存储在变量 ex 中。
- 在控制台上打印异常错误消息。
- catch 语句主体的结尾。
- 如果程序执行成功,它应该返回一个值。
- main() 函数体的结尾。
总结:
- 使用 C++ 中的异常处理,您可以处理运行时错误。
- 运行时错误是在程序执行过程中发生的错误。
- 异常处理可帮助您处理程序中的任何意外情况。
- 当发生意外情况时,程序控制权会转移到处理程序。
- 要捕获异常,您需要在 try-catch 块下放置一段代码。
- throw 关键字帮助程序抛出异常,帮助程序处理问题。
- try 关键字有助于识别将激活某些异常的代码块。
- 我们可以覆盖异常头文件的what()函数来定义我们的异常。
C语言