异常处理
程序错误通常分为两类:
- 逻辑错误:由编程失误导致的错误,例如“索引超出范围”
- 异常:超出程序的控制范围的错误条件,例如“网络服务不可用”、“内存不足”
许多编程语言都有对异常的处理,C++ 当然也不例外。
示例:
cpp
/**
* Copyright 2023 <Hardworking Bee>
*/
#include <iostream>
#include <limits>
#include <stdexcept>
void Test(int n) {
if (n > std::numeric_limits<char>::max()) {
throw std::overflow_error("n is too large");
}
}
int main() {
try {
Test(1000);
} catch (const std::overflow_error& e) {
std::cerr << e.what() << '\n';
return -1;
}
return 0;
}TIP
为了增强可读性和方便团队协作,如果函数内部可能抛出异常,建议声明异常类型。
cpp
void Test(int n) throw(std::overflow_error) {
if (n > std::numeric_limits<char>::max()) {
throw std::overflow_error("n is too large");
}
}自定义异常
在 C++ 中我们除了可以 throw 标准库已经定义了的异常,我们还可以 throw 任何类型,例如 throw -1、throw "This is an exception"。但一般而言,我们建议 throw 从 std::exception 直接或间接继承的类型。
示例:
cpp
/**
* Copyright 2023 <Hardworking Bee>
*/
#include <iostream>
#include <stdexcept>
class divide_error : public std::runtime_error {
public:
explicit divide_error(const std::string& msg) : std::runtime_error(msg) {}
};
class divide_by_zero : public divide_error {
public:
divide_by_zero() : divide_error("attempted to divide by zero") {}
};
int Divide(int a, int b) throw(divide_by_zero) {
if (b == 0) {
throw divide_by_zero();
}
return a / b;
}
int main() {
try {
Divide(1, 0);
} catch (const divide_by_zero& e) {
std::cerr << e.what() << '\n';
return -1;
}
return 0;
}std::runtime_error 继承 std::exception,表示运行时错误的异常。