假设有异常
enum class Table { Test, XX };
static std::string name(Table table) {
switch(table) {
case Table::Test: return "TEST";
default: throw std::invalid_argument("Unknown table");
}
}
当执行代码:
std::string xx = TableMeta::name(Table::XX);
会抛出异常
当异常被抛出时,如果没有在当前函数中被 catch 捕获,它会沿着调用栈向上传播,寻找合适的 catch 块来处理。
如果在整个程序中都没有找到匹配的 catch 块来处理这个异常,那么程序会调用 std::terminate 函数来终止程序的执行。在程序终止前,标准库通常会输出一些与异常相关的错误信息到标准错误流 stderr,然后就能看到自动打印错误日志。
如果我们手动写try catch捕获异常,就能接管C++的异常处理流程,可以自由打印输出,或者用其他形式停止程序,甚至不停止程序
try
{
std::string xx = TableMeta::name(Table::XX);
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
std::cout << "发生错误 按下任意键关闭程序\n";
std::cin.get();
return 1;
}
-
std::exception是所有异常派生类的基类,无论throw嵌套多深,最终都能被std::exception接收 -
e.what()本身就是类型为const char*的C风格字符串 - 不会捕获:非
std::exception类型的异常(如throw 42;)。 -
std::exception的派生类型
主要派生类(按功能分类)
1. 逻辑错误(std::logic_error)
表示程序逻辑错误,通常应在编码时避免:
-
std::invalid_argument→ 参数无效(例如函数接收到非法值) -
std::domain_error→ 数学运算定义域错误(如sqrt(-1)) -
std::length_error→ 超出容器长度限制(如std::vector::reserve过大) -
std::out_of_range→ 越界访问(如std::vector::at越界)
2. 运行时错误(std::runtime_error)
表示运行时发生的、难以预料的错误:
-
std::range_error→ 计算结果超出有效范围(如浮点数溢出) -
std::overflow_error→ 算术上溢(如INT_MAX + 1) -
std::underflow_error→ 算术下溢(如浮点数精度丢失) -
std::system_error→ 系统调用错误(如文件/网络操作失败)
3. 其他标准异常
-
std::bad_alloc→ 内存分配失败(new或malloc失败) -
std::bad_cast→dynamic_cast转换失败(RTTI 相关) -
std::bad_typeid→typeid操作失败(RTTI 相关) -
std::bad_exception→ 未预期的异常(罕见)
继承关系图示
std::exception
├── std::logic_error
│ ├── std::invalid_argument
│ ├── std::domain_error
│ ├── std::length_error
│ └── std::out_of_range
├── std::runtime_error
│ ├── std::range_error
│ ├── std::overflow_error
│ ├── std::underflow_error
│ └── std::system_error
├── std::bad_alloc
├── std::bad_cast
├── std::bad_typeid
└── std::bad_exception
使用示例
#include <stdexcept>
#include <vector>
void validate(int value) {
if (value < 0)
throw std::invalid_argument("值不能为负数");
}
int main() {
try {
std::vector<int> v = {1, 2, 3};
std::cout << v.at(10); // 抛出 std::out_of_range
}
catch (const std::out_of_range& e) {
std::cerr << "越界错误: " << e.what() << std::endl;
}
catch (const std::exception& e) {
std::cerr << "其他异常: " << e.what() << std::endl;
}
}
tips
优先捕获具体异常:先捕获派生类(如 std::out_of_range),再用 std::exception 兜底。