📅  最后修改于: 2023-12-03 14:59:51.412000             🧑  作者: Mango
在C++中,异常是程序的一种非正常事件,例如除以0、访问空指针等等。异常处理是指当程序出现异常时,如何优雅地处理这些异常以使程序能够正常运行或者让程序能够优雅地终止。
C++中的异常处理机制是一种将异常信息传递给调用者并在其中选择处理异常的方法的方式。当程序中出现异常时,程序将立即跳到最近的异常处理程序,并在那里处理异常。
在C++中,可以使用关键字throw
抛出异常。例如:
void divide(int a, int b)
{
if(b == 0)
{
throw "Divide by zero"; // 抛出异常
}
int c = a / b;
cout << "Result: " << c << endl;
}
在上面的例子中,如果除数b
为0,则使用throw
抛出一个字符串类型的异常:"Divide by zero"。
可以使用关键字try
和catch
捕获异常并进行处理。例如:
try
{
divide(10, 0); // 调用可能会抛出异常的函数
}
catch(const char* message) // 捕获异常
{
cerr << "Error: " << message << endl;
}
在上面的例子中,函数divide
可能会抛出异常,使用try
可以调用该函数。如果抛出了异常,则使用catch
捕获该异常并打印出错误信息。
可以使用多个catch
语句来处理不同类型的异常。例如:
try
{
// some code
}
catch(const char* message)
{
cerr << "Error: " << message << endl;
}
catch(const std::exception& e) // 捕获STL异常
{
cerr << "STL exception: " << e.what() << endl;
}
catch(...) // 捕获其他异常
{
cerr << "Unknown exception" << endl;
}
在上面的例子中,首先会捕获一个字符串类型的异常,如果没有捕获到,则会捕获STL的异常(例如std::out_of_range
),如果再没有捕获到,则会捕获其他类型的异常(但是不建议这样做)。
异常可以处理程序中出现的非正常事件,但是它们也会带来性能损失。因此,应该只在必要时才使用异常。例如,当IO流出现错误时,就应该使用异常。而在常规程序中,应该尽量避免使用异常。
当使用多个catch
语句时,应该优先捕获更具体的异常。例如:
try
{
// some code
}
catch(const std::out_of_range& e)
{
cerr << "Out of range: " << e.what() << endl;
}
catch(const std::exception& e)
{
cerr << "Exception: " << e.what() << endl;
}
在上面的例子中,应该先捕获std::out_of_range
异常,因为它是更具体的异常类型。
如果在函数声明时指定了异常说明,则必须在函数实现时遵守该说明。例如:
void divide(int a, int b) throw(const char*);
在上面的例子中,函数divide
声明了可能会抛出一个字符串类型的异常。如果在函数实现时没有抛出该类型的异常,编译器将会发出警告。
在异常抛出后,程序立即跳转到最近的catch
语句。因此,如果在其中没有处理异常,则程序将会崩溃。为此,在函数中使用try
/catch
语句时,需要在堆栈退出前释放资源。例如:
void divide(int a, int b)
{
ResourceGuard guard; // 自定义RAII类
if(b == 0)
{
throw "Divide by zero"; // 抛出异常
}
int c = a / b;
cout << "Result: " << c << endl;
}
在上面的例子中,使用了一个自定义的RAII类ResourceGuard
,在函数返回或抛出异常时,该类将会销毁并自动释放资源。
C++中的异常处理是一种优雅地处理程序中出现的非正常事件的方式。异常处理机制包括抛出异常和捕获异常两个方面。在使用异常时,应该只在必要时才使用,并捕获更具体的异常。同时,要注意在堆栈退出前释放资源。