C++ 异常处理
C++ 异常处理机制用于捕获并处理程序执行中的错误或异常情况。异常处理允许程序在运行时处理错误,而不会直接导致程序崩溃。C++ 的异常处理使用 try、throw 和 catch 语句来实现。
1. 异常处理基本概念
- throw:用于抛出异常。
- try:用于包含可能发生异常的代码块。
- catch:用于捕获并处理异常。
异常处理的目的是在发生异常时,通过捕获异常并采取适当的补救措施,防止程序崩溃。
2. 异常处理的基本语法
2.1 try-catch 语句
异常处理的基本结构是 try 块和 catch 块。代码块中的某些操作如果发生异常,将跳转到 catch 块处理。
#include <iostream>
using namespace std;
int main() {
try {
int x = 10;
int y = 0;
if (y == 0) {
throw "Division by zero error"; // 抛出异常
}
cout << x / y << endl;
}
catch (const char* e) {
// 捕获并处理异常
cout << "Error: " << e << endl;
}
return 0;
}
说明:
throw:用于抛出一个异常,可以抛出各种类型的数据,如整数、字符串、对象等。catch:用于捕获异常并处理。catch后面指定异常的类型。
2.2 多种类型的异常
你可以在 catch 块中捕获不同类型的异常,C++ 支持多重 catch 块来处理不同类型的异常。
#include <iostream>
using namespace std;
int main() {
try {
int choice = 2;
if (choice == 1) {
throw 10; // 抛出整型异常
} else if (choice == 2) {
throw "String exception"; // 抛出字符串异常
}
}
catch (int e) {
cout << "Caught an integer exception: " << e << endl;
}
catch (const char* e) {
cout << "Caught a string exception: " << e << endl;
}
return 0;
}
输出:
Caught a string exception: String exception
说明:
- 异常是按顺序匹配的,如果捕获到类型匹配的异常,就执行相应的
catch块。
3. 抛出异常(throw)
在 C++ 中,可以使用 throw 关键字抛出异常。你可以抛出任何类型的数据,包括基本数据类型、类对象等。
3.1 抛出内建类型的异常
#include <iostream>
using namespace std;
int main() {
try {
throw 404; // 抛出整型异常
}
catch (int e) {
cout << "Caught exception: " << e << endl;
}
return 0;
}
3.2 抛出类对象
你可以定义自己的类,并抛出类的对象。
#include <iostream>
using namespace std;
class MyException {
public:
void message() {
cout << "This is a custom exception!" << endl;
}
};
int main() {
try {
throw MyException(); // 抛出自定义类对象
}
catch (MyException e) {
e.message(); // 捕获并调用类的成员函数
}
return 0;
}
4. 异常的传播(异常的传播机制)
在 C++ 中,异常是从 throw 语句抛出的,并按照函数调用的堆栈层级逐层传播,直到被某个 catch 块捕获。如果在当前函数中没有捕获异常,异常会继续向外传播,直到找到合适的 catch 块。
4.1 函数中的异常传播
#include <iostream>
using namespace std;
void functionA() {
throw "Error in functionA"; // 抛出异常
}
void functionB() {
functionA(); // functionA 抛出的异常会被捕获
}
int main() {
try {
functionB(); // 异常最终会在 main 函数中被捕获
}
catch (const char* e) {
cout << "Caught exception: " << e << endl;
}
return 0;
}
输出:
Caught exception: Error in functionA
说明:
- 异常从
functionA中抛出,经过functionB后被main函数中的catch块捕获。
5. 异常的再抛出
在 catch 块中处理完异常后,可以选择再次抛出异常,将异常传递到外部,允许更高层的代码处理异常。
#include <iostream>
using namespace std;
void functionA() {
try {
throw "Error in functionA"; // 抛出异常
}
catch (const char* e) {
cout << "Caught in functionA: " << e << endl;
throw; // 再次抛出异常
}
}
int main() {
try {
functionA(); // 这里会捕获 functionA 再次抛出的异常
}
catch (const char* e) {
cout << "Caught in main: " << e << endl;
}
return 0;
}
输出:
Caught in functionA: Error in functionA
Caught in main: Error in functionA
6. 异常规范(C++11 异常声明)
C++11 引入了异常规范,用于指定哪些函数可以抛出哪些类型的异常。你可以通过 noexcept 声明某个函数不抛出任何异常。
6.1 noexcept
noexcept 用于表示函数不会抛出异常。如果函数声明为 noexcept,编译器会进行优化。
#include <iostream>
using namespace std;
void myFunction() noexcept { // 声明该函数不会抛出异常
cout << "This function does not throw exceptions." << endl;
}
int main() {
myFunction();
return 0;
}
6.2 throw()
在 C++11 之前,throw() 用于指定函数可能抛出的异常类型。但这种方式已被 noexcept 取代,throw() 已经过时。
void myFunction() throw(int) { // 仅抛出 int 类型异常
throw 10;
}
7. 总结
- throw:用于抛出异常,可以抛出内建类型或对象。
- try-catch:用于捕获异常并处理。
- 多重 catch:可以捕获不同类型的异常。
- 异常传播:异常会沿着调用栈向外传播,直到被捕获。
- noexcept:用于指定一个函数不会抛出异常。
异常处理机制使得 C++ 程序能够优雅地处理错误,而不会导致程序崩溃。通过合理使用异常处理,可以提高代码的鲁棒性和可靠性。