文章目录
概述
异常是指存在于运行时的反常行为,这些行为超出了函数正常功能的范围,当程序检测到一个它无法处理的问题,需要用到异常处理,异常处理机制为程序中异常检测
和异常处理
这两部分的协作提供支持。
C++中的异常处理包括以下内容:
throw 表达式(throw expression)
,异常检测部分使用 throw 表达式来表示它遇到了无法处理的问题。try...catch 语句块(try block)
,在 try 语句块中检测异常是否发生或者存在,在 catch 语句块中处理对应的异常。一套异常类(exception class)
,用于在 throw 表达式和相关的catch子句之间传递异常信息。
异常处理
throw 表达式
使用 throw 表达式引发一个异常, throw 表达式包含关键字 throw 和 紧随其后的一个表达式,其中表示的类型就是抛出的异常类型。
cpp
int main() {
//......
if (param > 20) {
throw runtime_error("Parameter outside.");
}
return 0;
}
try 语句块
try 语句块的标准语法形式如下:
cpp
try {
// 逻辑代码
} catch (异常声明1) {
// 处理方式
} catch (异常声明2) {
// 处理方式
}
当 try 中抛出了异常(使用了 throw)后,根据后续 catch 中的异常声明选择使用哪个 catch 来捕获抛出的异常,catch 结束后继续走到 try 的最后一个 catch 后的语句继续执行。
标准异常
C++标准库定义了一组类,用于报告标准库函数遇到的问题。
- exception 头文件定义了最通用的异常类 exception,它只报告异常的发生,不提供任何额外信息。
- stdexcept 头文件定义了几种常用的异常类。
- new 头文件定义了 bad_alloc 异常类型。
- type_info 头文件定义了 bad_cast 异常类。
其中常用的是 stdexcept 中的异常类,异常类定义如下:
异常类 | 描述 |
---|---|
exception | 最常见的问题 |
runtime_error | 只有在运行时才能检测出的问题 |
range_error | 运行时错误:生成的结果超出了有意义的值或者范围 |
overflow_error | 运行时错误:计算上溢 |
underflow_error | 运行时错误:计算下溢 |
logic_error | 程序逻辑错误 |
domain_error | 逻辑错误:参数对应的结果值不存在 |
invalid_argument | 逻辑错误:无效参数 |
length_error | 逻辑错误:试图创建一个超出该类型最大长度的对象 |
out_of_range | 逻辑错误:使用一个超出有效范围的值 |
简单示例
cpp
#include <iostream>
#include <map>
#include <stdexcept>
using namespace std;
int main() {
map<string, string> user_info;
user_info.insert(std::pair("A", "12345"));
user_info.insert(std::pair("B", "67890"));
user_info.insert(std::pair("C", "ADMIN"));
string find_use = "D";
try {
string password = user_info.at(find_use);
} catch (exception error) {
cout << error.what() << endl;
}
return 0;
}
运行结果
cmd
invalid map<K, T> key
自定义异常类
要自定义异常类需要继承std::exception ,std::exception 是所有异常类的基类,其中有一个 what()的虚函数
,自定义的异常类型都都实现这个函数即可,示例如下:
cpp
class UserException
: public exception {
public:
UserException(string & _key) {
message_ = "no key = " + _key;
}
const char* what() const noexcept override {
return message_.c_str();
}
private:
string message_;
};
使用示例
cpp
#include <iostream>
#include <map>
#include <stdexcept>
using namespace std;
int main() {
map<string, string> user_info;
user_info.insert(std::pair("A", "12345"));
user_info.insert(std::pair("B", "67890"));
user_info.insert(std::pair("C", "ADMIN"));
string find_use = "D";
try {
string password = user_info[find_use];
if (password.empty()) {
/* 抛出自定义异常类 */
throw UserException(find_use);
}
} catch (UserException error) {
cout << error.what() << endl;
}
return 0;
}