C++的异常处理机制是一套用于在程序运行时捕获和处理错误情况的规范方案,通过try、catch、throw三个关键字配合实现,能够在错误发生时将控制权转移到对应的处理逻辑中,避免程序直接崩溃。

C++异常处理基础语法
异常抛出
当程序执行过程中遇到错误情况时,可以使用throw关键字抛出一个异常对象,这个对象可以是基本数据类型、字符串或者自定义类的实例。抛出后程序会立刻停止当前执行流程,开始查找匹配的异常捕获逻辑。
下面是抛出基本类型异常的示例:
#include <iostream>
using namespace std;
int divide(int a, int b) {
if (b == 0) {
// 除数为0时抛出整型异常
throw -1;
}
return a / b;
}
int main() {
try {
int result = divide(10, 0);
cout << "计算结果:" << result << endl;
} catch (int e) {
cout << "捕获到异常,错误码:" << e << endl;
}
return 0;
}
try块与catch块
try块用于包裹可能会抛出异常的代码段,当try块内的代码抛出异常时,程序会依次匹配后面的catch块,找到和异常类型匹配的catch块后执行其中的处理逻辑。如果所有catch块都不匹配,异常会继续向外层传播,直到被捕获或者导致程序终止。
catch块的语法格式为catch (异常类型 变量名),可以捕获对应类型的异常,也可以使用catch (...)捕获所有类型的异常,作为兜底处理逻辑。
多个catch块匹配的示例:
#include <iostream>
#include <string>
using namespace std;
void testException(int type) {
if (type == 1) {
throw 100;
} else if (type == 2) {
throw "字符串异常";
} else if (type == 3) {
throw 3.14;
}
}
int main() {
try {
testException(2);
} catch (int e) {
cout << "捕获整型异常:" << e << endl;
} catch (const char* e) {
cout << "捕获字符串异常:" << e << endl;
} catch (...) {
cout << "捕获到其他类型异常" << endl;
}
return 0;
}
自定义异常类型
实际开发中通常会自定义异常类,来携带更丰富的错误信息,比如错误描述、错误码、发生错误的位置等。自定义异常类一般会继承标准库的exception类,重写what方法返回错误描述。
自定义异常类的使用示例:
#include <iostream>
#include <exception>
#include <string>
using namespace std;
// 自定义异常类,继承标准exception
class MyException : public exception {
private:
string errMsg;
public:
MyException(const string& msg) : errMsg(msg) {}
// 重写what方法,返回错误描述
const char* what() const noexcept override {
return errMsg.c_str();
}
};
void processData(int value) {
if (value < 0) {
throw MyException("数据值不能为负数");
}
cout << "处理数据:" << value << endl;
}
int main() {
try {
processData(-5);
} catch (const MyException& e) {
cout << "捕获自定义异常:" << e.what() << endl;
} catch (const exception& e) {
cout << "捕获标准异常:" << e.what() << endl;
}
return 0;
}
异常处理的注意事项
- 不要在析构函数中抛出异常,否则可能导致程序在栈展开过程中调用
terminate函数终止运行。 - 抛出的异常对象在传递到catch块的过程中会发生拷贝,因此自定义异常类最好实现拷贝构造函数,避免浅拷贝问题。
- catch块的匹配顺序是从上到下的,因此更具体的异常类型应该放在前面,通用的
catch (...)放在最后。 - 如果函数声明了异常规范,比如
void func() throw(int, string),表示该函数只会抛出int或string类型的异常,不过C++11之后更推荐使用noexcept关键字来标识函数是否抛出异常。
异常安全相关概念
异常安全是指当异常发生时,程序不会泄露资源,也不会破坏数据的一致性,通常分为三个级别:
- 基本异常安全:异常发生后,程序的状态仍然有效,不会出现数据损坏,但可能部分操作没有完成。
- 强异常安全:异常发生后,程序的状态会回滚到操作执行之前的状态,就像操作没有发生过一样。
- 不抛异常安全:函数保证不会抛出任何异常,比如使用
noexcept修饰的函数。
要实现异常安全,通常会结合RAII机制,将资源的管理封装在对象的构造函数和析构函数中,这样即使发生异常,对象的析构函数也会自动被调用,释放已经获取的资源,避免内存泄漏等问题。