在运行 C++ 代码时,可能会发生各种类型的故障,包括由于不正确的输入或程序员的编码错误造成的故障。当出现问题时,C++ 通常会停止并生成错误消息。这在 C++ 中称为抛出异常(这将抛出错误)。
C++ 中的异常处理允许您处理运行时错误等不可预见的情况。因此,如果发生意外事件,程序的控制权将传递给处理程序,这些处理程序是特殊函数。
您将程序代码的某个部分置于异常检查之下,以捕获异常。try-catch 块包含代码的特定区域。
如果该代码区域内发生异常情况,则一定会抛出异常。程序随后会将控制权传递给异常处理程序。
如果没有出现异常情况,代码将正常运行。处理程序将不予考虑。
C++ 中的异常处理用于以下原因:
throw: 当程序遇到问题时,它会抛出异常。在程序中,throw 关键字促进了抛出操作。
catch: 为了处理异常,程序使用异常处理程序。它插入到程序中必须处理问题的部分。这是通过使用 catch 关键字实现的。
try: try 标识将调用特定异常的代码段。其后应放置一个或多个 catch 块。
假设一个代码块将抛出异常。通过使用 try-and-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。
以下是一个基本的 C++ 异常处理示例。程序输出中描述了 try/catch 块的执行流程。
#include <iostream>
using namespace std;
int main()
{
int x = -1;
// Some code
cout << "Before the try \n";
try {
cout << "Inside the try \n";
if (x < 0)
{
throw x;
cout << "After the throw (Never executed) \n";
}
}
catch (int x ) {
cout << "Exception Caught \n";
}
cout << "After catch (Will be executed) \n";
return 0;
}
输出
Before the try Inside the try Exception Caught After catch (Will be executed)
为了捕获所有异常类型,有一个特殊的 catch 块,称为“catch-all”块,表示为 catch(...)。例如,在以下程序中,当抛出 int 作为异常时,catch(...) 块将运行,因为没有针对 int 的 catch 块。
#include <iostream>
using namespace std;
int main()
{
try {
throw 10;
}
catch (char *excp) {
cout << "Caught " << excp;
}
catch (...) {
cout << "The Default Exception\n";
}
return 0;
}
输出
The Default Exception
对于基本类型,没有隐式类型转换。例如,在以下程序中,“a”不会隐式转换为 int。
#include <iostream>
using namespace std;
int main()
{
try {
throw 'a';
}
catch (int x) {
cout << "Caught " << x;
}
catch (...) {
cout << " The Default Exception\n";
}
return 0;
}
输出
The Default Exception
如果抛出异常但未在某处捕获,则程序会异常终止。例如,在下面的程序中抛出了一个 char,但未被 catch 块捕获。
#include <iostream>
using namespace std;
int main()
{
try {
throw 'a';
}
catch (int x) {
cout << "Caught ";
}
return 0;
}
输出
terminate called after throwing an instance of 'char' timeout: the monitored command dumped core
派生类异常之后应处理基类异常。
C++ 库提供了一个标准异常类,它作为所有标准异常的根类,类似于 Java。标准库组件抛出的所有对象都继承自该类。因此,通过捕获此类型,可以捕获所有常见异常。
与 Java 不同,C++ 中的所有异常都是未检查的,这意味着编译器不会确定异常是否被捕获(有关详细信息,请参阅此处)。因此,不需要在函数定义中列出所有未捕获的异常。尽管如此,这样做是一个好主意。
#include <iostream>
using namespace std;
// Here we mainly specify the exceptions that this function will
// throws.
void fun(int *ptr, int x) throw (int *, int) // Dynamic Exception specification
{
if (ptr == NULL)
throw ptr;
if (x == 0)
throw x;
/* Some functionality */
}
int main()
{
try {
fun(NULL, 0);
}
catch(...) {
cout << "Caught the exception from fun()";
}
return 0;
}
输出
Caught the exception from fun()
在 C++ 中,try/catch 块可以嵌套。此外,可以使用“throw;”重新抛出异常
#include <iostream>
using namespace std;
int main()
{
try {
try {
throw 50;
}
catch (int n) {
cout << "Handle Partially ";
throw; // Re-throwing an exception
}
}
catch (int n) {
cout << "Handle remaining ";
}
return 0;
}
输出
Handle Partially Handle remaining
抛出异常时,try 块内创建的所有对象在控制权传递给 catch 块之前都会被销毁。
#include <iostream>
using namespace std;
class Test {
public:
Test() { cout << "Constructor of Test " << endl; }
~Test() { cout << "Destructor of Test " << endl; }
};
int main()
{
try {
Test t1;
throw 50;
}
catch (int i) {
cout << "Caught " << i << endl;
}
}
输出
Constructor of Test Destructor of Test Caught 50