C++ 异常处理:Try、Catch、Throw 示例
什么是 C++ 异常处理?
C++ 中的异常处理为您提供了一种处理意外情况(如运行时错误)的方法。因此,当发生意外情况时,程序控制将被转移到称为处理程序的特殊函数。
为了捕获异常,您会将某些代码段置于异常检查之下。该代码段位于 try-catch 块内。
如果在该代码段中发生异常情况,将抛出异常。接下来,异常处理程序将接管程序的控制权。
如果没有发生异常情况,代码将正常执行。处理程序将被忽略。
在本 C++ 教程中,您将学习
为什么需要异常处理?
以下是使用 C++ 异常处理的原因:
- 您将把错误处理代码与正常代码分开。代码将更具可读性,更易于维护。
- 函数可以处理它们选择的异常。即使函数抛出许多异常,它也只会处理其中一些。调用者将处理未捕获的异常。
异常处理关键字
C++ 中的异常处理围绕这三个关键字展开:
- throw – 当程序遇到问题时,它会抛出异常。throw 关键字帮助程序执行抛出操作。
- catch – 程序使用异常处理程序来捕获异常。它被添加到程序中需要处理问题的部分。这是使用 catch 关键字完成的。
- try – 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 头文件以使用其函数。
- 在程序中包含 vector 头文件以使用其函数。
- 在程序中包含 std 命名空间,以便在不调用它的情况下使用其类。
- 调用 main() 函数。程序逻辑应添加到其主体中。
- 创建一个名为 vec 的向量来存储整数数据。
- 向名为 vec 的向量添加元素 0。
- 向名为 vec 的向量添加元素 1。
- 注释。它将被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。该函数应返回 double 类型的结果。
- 使用 if 语句检查变量参数 y 的值是否为 0。{ 标记 if 主体的开头。
- 如果 y 为 0,则返回/抛出的消息。
- if 语句主体的结束。
- zeroDivision 函数应返回 x/y 的值。
- zeroDivision 函数的结尾。
- 调用 main() 方法。{ 标记此方法的开头。
- 声明一个整数变量并为其赋值 11。
- 声明一个整数变量 b 并为其赋值 0。
- 声明一个 double 变量 c 并为其赋值 0。
- 使用 try 语句捕获异常。{ 标记 try/catch 块的开头。添加到该块中的代码将成为受保护代码。
- 调用 zeroDivision 函数,并将参数 a 和 b,即 11 和 0,传递给它。此操作的结果将存储在变量 c 中。
- 在控制台上打印变量 c 的值。
- try/catch 块的结尾。
- 捕获异常。返回的错误消息将存储在变量 message 中。
- 在控制台上打印返回的错误消息。
- catch 块的结尾。
- 程序应在成功执行后返回值。
- main() 函数主体的结尾。
C++ 标准异常
C++ 随附一个在 <exception> 类中定义的标准异常列表。这些如下所述:
| Exception | 描述 |
|---|---|
| std::exception | 这是一个异常,也是所有标准 C++ 异常的父类。 |
| std::bad_alloc | 此异常由 new 关键字抛出。 |
| std::bad_cast | 这是由 dynamic_cast 抛出的异常。 |
| std::bad_exception | C++ 程序中处理意外异常的有用设备。 |
| std::bad_typeid | 由 typeid 抛出的异常。 |
| std::logic_error | 理论上可以通过阅读代码检测到此异常。 |
| std::domain_error | 这是在使用数学上无效的域后抛出的异常。 |
| std::invalid_argument | 用于无效参数时抛出的异常。 |
| std::length_error | 创建过大的 std::string 后抛出的异常。 |
| std::out_of_range | 由 at() 方法抛出。 |
| std::runtime_error | 这是无法通过阅读代码检测到的异常。 |
| std::overflow_error | 在发生数学溢出后抛出的此异常。 |
| std::range_error | 尝试存储超出范围的值时抛出的此异常。 |
| std::underflow_error | 发生数学下溢后抛出的异常。 |
用户定义异常
C++ std::exception 类允许我们定义可以作为异常抛出的对象。此类已在 <exception> 头文件中定义。该类为我们提供了一个名为 what 的虚拟成员函数。
此函数返回 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 头文件。我们将使用其函数而不会出错。
- 在我们的程序中包含 exception 头文件。我们将使用其 like what 等函数而不会出错。
- 在程序中包含 std 命名空间,以便在使用其类时无需调用它。
- 创建一个名为 newException 的新类。此类继承 C++ 的 exception 类。
- 类主体的开头。
- 重写 exception 头文件中定义的虚拟成员函数 what()。然后我们将描述我们自己的异常,即 new exception。
- 开始 new exception 的定义。
- 捕获 new exception 时要返回的消息。
- new exception 主体的结尾。
- newException 类的结尾。newex 是捕获我们新异常后将使用的名称,然后将调用 newException。
- 调用 main() 函数。程序逻辑应添加到其主体中。{ 标记其主体的开头。
- 使用 try 语句标记我们需要标记异常的代码。{ 标记 try/catch 块的开头。被此包围的代码将成为受保护代码。
- 如果捕获到 newex 异常,则抛出它。
- try 主体的结尾。
- 使用 catch 语句捕获异常。异常错误消息将存储在变量 ex 中。
- 在控制台上打印异常错误消息。
- catch 语句主体的结尾。
- 如果程序成功执行,则应返回值。
- main() 函数体结束。
摘要
- 通过 C++ 的异常处理,您可以处理运行时错误。
- 运行时错误是在程序执行期间发生的错误。
- 异常处理可帮助您处理程序中的任何意外情况。
- 当意外情况发生时,程序控制被转移到处理程序。
- 要捕获异常,您需要将一段代码放置在 try-catch 块下。
- throw 关键字帮助程序抛出异常,从而帮助程序处理问题。
- try 关键字有助于识别将激活某些异常的代码块。
- 我们可以重写 exception 头文件的 what() 函数来定义我们的异常。




