C++ Primer 学习笔记-异常处理

文章目录

概述

异常是指存在于运行时的反常行为,这些行为超出了函数正常功能的范围,当程序检测到一个它无法处理的问题,需要用到异常处理,异常处理机制为程序中异常检测异常处理这两部分的协作提供支持。

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;
}
相关推荐
机智的叉烧17 分钟前
前沿重器[57] | sigir24:大模型推荐系统的文本ID对齐学习
人工智能·学习·机器学习
量子-Alex1 小时前
【多模态聚类】用于无标记视频自监督学习的多模态聚类网络
学习·音视频·聚类
吉大一菜鸡1 小时前
FPGA学习(基于小梅哥Xilinx FPGA)学习笔记
笔记·学习·fpga开发
CCSBRIDGE4 小时前
Magento2项目部署笔记
笔记
爱吃西瓜的小菜鸡4 小时前
【C语言】判断回文
c语言·学习·算法
别NULL4 小时前
机试题——疯长的草
数据结构·c++·算法
小A1594 小时前
STM32完全学习——SPI接口的FLASH(DMA模式)
stm32·嵌入式硬件·学习
亦枫Leonlew4 小时前
微积分复习笔记 Calculus Volume 2 - 5.1 Sequences
笔记·数学·微积分
岁岁岁平安5 小时前
spring学习(spring-DI(字符串或对象引用注入、集合注入)(XML配置))
java·学习·spring·依赖注入·集合注入·基本数据类型注入·引用数据类型注入
武昌库里写JAVA5 小时前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计