当前位置: 首页 > article >正文

C++异常处理 throw try catch

C++ 异常处理概述

C++ 异常处理机制提供了一种在程序运行时捕获错误或异常情况的方式。异常处理的目的是使得程序在遇到错误时能够优雅地终止或恢复,并防止程序出现崩溃。C++ 使用 try, throw, 和 catch 关键字来实现异常处理。

异常处理的基本结构:

  1. throw: 用来抛出异常,可以是任意类型的对象。

  2. try: 用来包裹可能抛出异常的代码块。

  3. catch: 用来捕获特定的异常类型并处理。

1. throw 关键字

throw 用于抛出异常。当程序执行到 throw 时,会跳出当前的代码块,异常被抛出,程序开始寻找相应的 catch 语句。

  • 语法throw expression;

    • expression 可以是任何数据类型,通常是一个异常对象。

    • 可以抛出内建类型、类对象、指针等。

throw 42;  // 抛出整数 42
throw std::runtime_error("An error occurred");  // 抛出异常对象

2. try

try 块是包含可能会抛出异常的代码的区域。当 try 块中的代码抛出异常时,控制权会跳转到相应的 catch 块中。

  • 语法

    try {// 可能抛出异常的代码
    }
    

3. catch

catch 用于捕获异常,并且可以处理它。catch 块的形式取决于抛出的异常类型。如果异常类型匹配,catch 语句就会捕获它。

  • 语法

    catch (ExceptionType e) {// 处理异常
    }
    
    • 你可以捕获特定的异常类型,也可以使用通用的 catch(...) 来捕获任何类型的异常。

基本的异常处理示例:

#include <iostream>
#include <stdexcept>  // std::runtime_errorvoid testFunction() {throw std::runtime_error("An error occurred");
}int main() {try {testFunction();  // 可能抛出异常的函数}catch (const std::exception& e) {  // 捕获异常std::cout << "Caught exception: " << e.what() << std::endl;}return 0;
}

详细讲解:

1. 抛出异常

try 块中,可能会发生错误。此时,你可以使用 throw 语句来抛出异常对象。你可以抛出任何类型的对象,常见的类型包括:

  • 基本数据类型(如 int, double

  • 类或结构体对象

  • 标准库异常类(如 std::exception, std::runtime_error

例子:

throw std::out_of_range("Index out of range");  // 抛出标准异常对象

2. 捕获异常

catch 块会根据其类型匹配捕获不同的异常对象。你可以为不同的异常类型设置多个 catch 块。异常处理机制是基于异常类型进行匹配的,匹配成功的 catch 块会执行。

try {// 代码可能抛出不同类型的异常throw 42;
}
catch (int e) {  // 捕获 int 类型异常std::cout << "Caught an integer: " << e << std::endl;
}
catch (std::exception& e) {  // 捕获所有继承自 std::exception 的异常std::cout << "Caught exception: " << e.what() << std::endl;
}

3. 通用的异常捕获

如果你不确定抛出的异常类型,可以使用一个通用的 catch(...) 来捕获所有未明确捕获的异常。

try {// 代码可能抛出不同类型的异常throw "Something went wrong";
}
catch (...) {  // 捕获所有类型的异常std::cout << "Caught an unknown exception" << std::endl;
}

4. 异常传递

当一个异常被抛出后,程序会按照“栈展开”的方式逐级寻找匹配的 catch 块。找不到时,程序会终止。

例如,如果 main() 中的 catch 无法捕获异常,异常将会沿着调用栈传递,直到程序终止。

5. 多重异常处理

你可以使用多个 catch 块来捕获不同类型的异常,确保程序对各种错误情况作出处理。

try {throw std::out_of_range("Out of range error");
}
catch (const std::out_of_range& e) {std::cout << "Caught out_of_range: " << e.what() << std::endl;
}
catch (const std::exception& e) {std::cout << "Caught exception: " << e.what() << std::endl;
}
catch (...) {std::cout << "Caught unknown exception" << std::endl;
}

6. 异常的传播

C++ 允许在多个函数中抛出异常。当函数内的代码抛出异常时,控制权会跳转到调用该函数的地方。如果异常未被捕获,则程序会终止。

void funcA() {throw std::runtime_error("Error in funcA");
}void funcB() {funcA();  // 异常从 funcA 传播到 funcB
}int main() {try {funcB();}catch (const std::exception& e) {std::cout << "Caught in main: " << e.what() << std::endl;}
}

7. 自定义异常

你可以定义自定义的异常类型,通过继承 std::exception 或其他异常类来创建自己的异常类。

class MyException : public std::exception {
public:const char* what() const noexcept override {return "My custom exception occurred";}
};void test() {throw MyException();  // 抛出自定义异常
}int main() {try {test();}catch (const MyException& e) {std::cout << "Caught custom exception: " << e.what() << std::endl;}
}

C++ 标准库异常类概述

C++ 标准库定义了一些通用的异常类,它们位于 <stdexcept> 头文件中。这些异常类帮助程序员识别和处理不同类型的错误。C++ 标准库异常类通常都继承自 std::exception,这是所有标准异常类的基类。

1. std::exception

std::exception 是 C++ 标准库异常体系的基类。它提供了一个虚函数 what(),返回一个指向常量字符数组的指针,用于描述异常的相关信息。

  • 定义

    class exception {
    public:virtual const char* what() const noexcept;
    };
    
    • what() 方法返回异常信息的描述。

    • noexcept 说明该函数不会抛出异常。

std::exception 是所有标准异常类的父类。如果你创建自定义的异常类,可以继承 std::exception 来提供异常描述。

示例

#include <iostream>
#include <stdexcept>int main() {try {throw std::exception();}catch (const std::exception& e) {std::cout << "Caught exception: " << e.what() << std::endl;}return 0;
}

输出:

Caught exception: 

2. std::runtime_error

std::runtime_error 继承自 std::exception,表示程序在运行时遇到的错误,通常是不可预料的错误。它的构造函数接受一个描述错误的字符串,该字符串将通过 what() 方法返回。

  • 定义

    class runtime_error : public exception {
    public:explicit runtime_error(const char* what_arg);explicit runtime_error(const std::string& what_arg);
    };
    

示例

#include <iostream>
#include <stdexcept>int main() {try {throw std::runtime_error("Runtime error occurred!");}catch (const std::runtime_error& e) {std::cout << "Caught runtime_error: " << e.what() << std::endl;}return 0;
}

输出:

Caught runtime_error: Runtime error occurred!

std::runtime_error 通常用于处理程序在运行时出现的异常情况,例如文件操作失败、网络连接错误等。

3. std::logic_error

std::logic_error 也继承自 std::exception,表示程序中的逻辑错误。这些错误通常是程序设计或实现上的错误,通常是程序员在编写程序时犯的错误。常见的逻辑错误包括访问无效的索引、非法的参数传递等。

  • 定义

    class logic_error : public exception {
    public:explicit logic_error(const char* what_arg);explicit logic_error(const std::string& what_arg);
    };
    

示例

#include <iostream>
#include <stdexcept>void test(int x) {if (x < 0) {throw std::logic_error("Negative value passed");}
}int main() {try {test(-1);  // 将抛出逻辑错误}catch (const std::logic_error& e) {std::cout << "Caught logic_error: " << e.what() << std::endl;}return 0;
}

输出:

Caught logic_error: Negative value passed

std::logic_error 通常用于处理程序在设计上就不应该发生的错误。

4. std::out_of_range

std::out_of_range 继承自 std::logic_error,用于表示访问超出有效范围的错误。通常用于数组、容器、指针等操作超出有效范围时。

  • 定义

    class out_of_range : public logic_error {
    public:explicit out_of_range(const char* what_arg);explicit out_of_range(const std::string& what_arg);
    };
    

示例

#include <iostream>
#include <stdexcept>
#include <vector>int main() {std::vector<int> vec = {1, 2, 3};try {std::cout << vec.at(5) << std::endl;  // 访问越界元素}catch (const std::out_of_range& e) {std::cout << "Caught out_of_range: " << e.what() << std::endl;}return 0;
}

输出:

Caught out_of_range: vector::_M_range_check

std::out_of_range 常用于检查容器操作时索引越界的情况。

5. std::invalid_argument

std::invalid_argument 继承自 std::logic_error,用于表示函数或操作接收到一个非法的参数。这通常是当函数的参数不符合预期时抛出的异常。

  • 定义

    class invalid_argument : public logic_error {
    public:explicit invalid_argument(const char* what_arg);explicit invalid_argument(const std::string& what_arg);
    };
    

示例

#include <iostream>
#include <stdexcept>void test(int x) {if (x <= 0) {throw std::invalid_argument("Argument must be positive");}
}int main() {try {test(0);  // 传递非法参数}catch (const std::invalid_argument& e) {std::cout << "Caught invalid_argument: " << e.what() << std::endl;}return 0;
}

输出:

Caught invalid_argument: Argument must be positive

std::invalid_argument 通常用于检测函数参数的合法性。

6. std::length_error

std::length_error 继承自 std::logic_error,用于表示容器或其他数据结构在处理时超过了其最大容量。比如在向一个固定大小的容器中插入元素时,超出了容器的最大长度。

  • 定义

    class length_error : public logic_error {
    public:explicit length_error(const char* what_arg);explicit length_error(const std::string& what_arg);
    };
    

示例

#include <iostream>
#include <stdexcept>
#include <vector>int main() {try {std::vector<int> vec(10);vec.resize(100);  // 超出容器允许的长度}catch (const std::length_error& e) {std::cout << "Caught length_error: " << e.what() << std::endl;}return 0;
}

输出:

Caught length_error: vector::resize

std::length_error 用于指示容器长度超过限制。

7. std::overflow_error

std::overflow_error 继承自 std::runtime_error,表示算术操作发生溢出(如整数加法超出了可表示的范围)。这种错误通常发生在数值计算时。

  • 定义

    class overflow_error : public runtime_error {
    public:explicit overflow_error(const char* what_arg);explicit overflow_error(const std::string& what_arg);
    };
    

示例

#include <iostream>
#include <stdexcept>int main() {try {int a = 2147483647;  // 假设int是32位,最大值为2147483647a = a + 1;  // 发生溢出throw std::overflow_error("Integer overflow");}catch (const std::overflow_error& e) {std::cout << "Caught overflow_error: " << e.what() << std::endl;}return 0;
}

输出:

Caught overflow_error: Integer overflow

std::overflow_error 用于表示溢出错误。

8. std::underflow_error

std::underflow_error 继承自 std::runtime_error,表示算术操作发生下溢(例如浮点数计算的下溢)。

更多的异常类: C++ 异常处理
在这里插入图片描述

相关文章:

C++异常处理 throw try catch

C 异常处理概述 C 异常处理机制提供了一种在程序运行时捕获错误或异常情况的方式。异常处理的目的是使得程序在遇到错误时能够优雅地终止或恢复&#xff0c;并防止程序出现崩溃。C 使用 try, throw, 和 catch 关键字来实现异常处理。 异常处理的基本结构&#xff1a; throw: …...

纯css实现环形进度条

需要在中实现一个定制化的环形进度条&#xff0c;最终效果如图&#xff1a; 使用代码 <divclass"circular-progress":style"{--progress: nextProgress,--color: endSliderColor,--size: isFull ? 60rpx : 90rpx,}"><div class"inner-conte…...

0基础 | 硬件 | 电源系统 一

降压电路LDO 几乎所有LDO都是基于此拓扑结构 图 拓扑结构 LDO属于线性电源&#xff0c;通过控制开关管的导通程度实现稳压&#xff0c;输出纹波小&#xff0c;无开关噪声 线性电源&#xff0c;IoutIin&#xff0c;发热功率P电压差△U*电流I&#xff0c;转换效率Vo/Vi LDO不适…...

详解 MySQL 索引的最左前缀匹配原则

MySQL 的最左前缀匹配原则主要是针对复合索引&#xff08;也称为联合索引&#xff09;而言的。其核心思想是&#xff1a;只有查询条件中包含索引最左侧&#xff08;第一列&#xff09;开始的连续一段列&#xff0c;才能让 MySQL 有效地利用该索引。 一、 复合索引的结构 复合…...

蓝桥杯算法题1

前言 双指针 唯一的雪花 Unique Snowflakes #include<iostream> #include<unordered_map> using namespace std; //这道题的意思就是在一个数组找一个最大的1区间的长度&#xff0c;这个区间里面没有重复数据 //如果暴力解法&#xff0c;每次求出以a[i]开头的满…...

【愚公系列】《高效使用DeepSeek》053-工艺参数调优

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…...

Cortex-M系列MCU的位带操作

Cortex-M系列位带操作详解 位带&#xff08;Bit-Banding&#xff09;是Cortex-M3/M4等处理器提供的一种硬件特性&#xff0c;允许通过别名地址对内存或外设寄存器中的单个位进行原子读-改-写操作&#xff0c;无需禁用中断或使用互斥锁。以下是位带操作的完整指南&#xff1a; …...

大坑!GaussDB数据库批量插入数据变只读

大坑!GaussDB数据库批量插入数据变只读 GaussDB插入数据时变只读df和du为什么不一致GaussDB磁盘空间使用阈值GaussDB变只读怎么办正确删除表的姿势GaussDB插入数据时变只读 涉及的数据库版本为:GaussDB Kernel 505.1.0 build da28c417。 GuassDB TPCC灌数报错DML失败,数据…...

35信号和槽_信号槽小结

Qt 信号槽 1.信号槽是啥~~ 尤其是和 Linux 中的信号进行了对比&#xff08;三要素&#xff09; 1) 信号源 2) 信号的类型 3)信号的处理方式 2.信号槽 使用 connect 3.如何查阅文档. 一个控件&#xff0c;内置了哪些信号&#xff0c;信号都是何时触发 一…...

获取KUKA机器人诊断文件KRCdiag的方法

有时候在进行售后问题时需要获取KUKA机器人的诊断文件KRCdiag&#xff0c;通过以下方法可以获取KUKA机器人的诊断文件KRCdiag&#xff1a; 1、将U盘插到控制柜内的任意一个USB接口&#xff1b; 2、依次点【主菜单】—【文件】—【存档】—【USB&#xff08;控制柜&#xff09…...

一周学会Pandas2 Python数据处理与分析-NumPy数据类型

锋哥原创的Pandas2 Python数据处理与分析 视频教程&#xff1a; 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili NumPy 提供了丰富的数据类型&#xff08;dtypes&#xff09;&#xff0c;主要用于高效数值计算。以下是 NumPy 的主要…...

Redis核心机制-缓存、分布式锁

目录 缓存 缓存更新策略 定期生成 实时生成 缓存问题 缓存预热&#xff08;Cache preheating&#xff09; 缓存穿透&#xff08;Cache penetration&#xff09; 缓存雪崩&#xff08;Cache avalanche&#xff09; 缓存击穿&#xff08;Cache breakdown&#xff09; 分…...

Three.js 系列专题 1:入门与基础

什么是 Three.js? Three.js 是一个基于 WebGL 的 JavaScript 库,它简化了 3D 图形编程,让开发者无需深入了解底层 WebGL API 就能创建复杂的 3D 场景。它广泛应用于网页游戏、可视化、虚拟现实等领域。 学习目标 理解 Three.js 的核心组件:场景(Scene)、相机(Camera)…...

[C++面试] 如何在特定内存位置上分配内存、构造对象

new面试-高阶题&#xff08;可以主动讲给面试官&#xff09;&#xff0c;适用于内存池、高性能场景或需要精确控制内存布局的编程需求。 一、核心方法&#xff1a;placement new placement new 是C中一种特殊形式的new运算符&#xff0c;允许在预先分配好的内存地址上构造对象…...

针对Ansible执行脚本时报错“可执行文件格式错误”,以下是详细的解决步骤和示例

针对Ansible执行脚本时报错“可执行文件格式错误”&#xff0c;以下是详细的解决步骤和示例&#xff1a; 目录 一、错误原因分析二、解决方案1. 检查并添加可执行权限2. 修复Shebang行3. 转换文件格式&#xff08;Windows → Unix&#xff09;4. 检查脚本内容兼容性5. 显式指定…...

如何在Ubuntu上安装Dify

如何在Ubuntu上安装Dify 如何在Ubuntu上安装docker 使用apt安装 # Add Dockers official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg…...

Python FastApi(13):APIRouter

如果你正在开发一个应用程序或 Web API&#xff0c;很少会将所有的内容都放在一个文件中。FastAPI 提供了一个方便的工具&#xff0c;可以在保持所有灵活性的同时构建你的应用程序。假设你的文件结构如下&#xff1a; . ├── app # 「app」是一个 Python 包…...

Harmony OS“一多” 详解:基于窗口变化的断点自适应实现

一、一多开发核心概念&#xff08;18N模式&#xff09; 目标&#xff1a;一次开发多端部署 解决的问题&#xff1a; 1、界面级一多&#xff1a;适配不同屏幕尺寸 2、功能级一多&#xff1a;设备功能兼容性处理(CanIUser) 3、工…...

【算法竞赛】状态压缩型背包问题经典应用(蓝桥杯2019A4分糖果)

在蓝桥杯中遇到的这道题&#xff0c;看上去比较普通&#xff0c;但其实蕴含了很巧妙的“状态压缩 背包”的思想&#xff0c;本文将从零到一&#xff0c;详细解析这个问题。 目录 一、题目 二、思路分析&#xff1a;状态压缩 最小覆盖 1. 本质&#xff1a;最小集合覆盖问题…...

kali——masscan

目录 前言 使用方法 前言 Masscan 是一款快速的端口扫描工具&#xff0c;在 Kali Linux 系统中常被用于网络安全评估和渗透测试。 使用方法 对单个IP进行端口扫描&#xff1a; masscan -p11-65535 192.168.238.131 扫描指定端口&#xff1a; masscan -p80,22 192.168.238.131…...

常微分方程 1

slow down and take your time 定积分应用回顾常微分方程的概述一阶微分方程可分离变量齐次方程三阶线性微分方程 一阶线性微分方程不定积分的被积分函数出现了绝对值梳理微分方程的基本概念题型 1 分离变量题型 2 齐次方程5.4 题型 3 一阶线性微分方程知识点5.55.6 尾声 定积分…...

Web前端页面搭建

1.在D盘中创建www文件 cmd进入窗口命令windowsR 切换盘符d: 进入创建的文件夹 在文件夹里安装tp框架 在PS中打开tp文件 创建网站&#xff0c;根目录到public 在浏览器中打开网页 修改文件目录名称 在public目录中的。htaccess中填写下面代码 <IfModule mod_rewrite.c >…...

开源 LLM 应用开发平台 Dify 全栈部署指南(Docker Compose 方案)

开源 LLM 应用开发平台 Dify 全栈部署指南&#xff08;Docker Compose 方案&#xff09; 一、部署环境要求与前置检查 1.1 硬件最低配置 组件要求CPU双核及以上内存4GB 及以上磁盘空间20GB 可用空间 1.2 系统兼容性验证 ✅ 官方支持系统&#xff1a; Ubuntu 20.04/22.04 L…...

BN 层的作用, 为什么有这个作用?

BN 层&#xff08;Batch Normalization&#xff09;——这是深度神经网络中非常重要的一环&#xff0c;它大大改善了网络的训练速度、稳定性和收敛效果。 &#x1f9e0; 一句话理解 BN 层的作用&#xff1a; Batch Normalization&#xff08;批归一化&#xff09;通过标准化每一…...

JavaScript 中常见的鼠标事件及应用

JavaScript 中常见的鼠标事件及应用 在 JavaScript 中&#xff0c;鼠标事件是用户与网页进行交互的重要方式&#xff0c;通过监听这些事件&#xff0c;开发者可以实现各种交互效果&#xff0c;如点击、悬停、拖动等。 在 JavaScript 中&#xff0c;鼠标事件类型多样&#xff0…...

【nginx】Nginx的功能特性及常用功能

目录 1.核心功能特性1.1 高并发处理能力1.2 反向代理与负载均衡1.3 静态资源服务1.4 缓存加速1.5 SSL/TLS支持1.6 动态模块扩展1.7 流媒体服务1.8 高可用性 2.常用功能场景2.1 反向代理与负载均衡2.2 静态资源服务2.3 缓存加速2.4 HTTPS支持2.5 API网关2.6 微服务网关 3.优势总…...

make_01_Program_01_makefile .SECONDARY .dirstamp 是什么功能

在 Makefile 中&#xff0c;.SECONDARY 和 .dirstamp 与 GNU Make 处理文件和目标的方式有关。让我们分别解释这两个部分&#xff0c;以及它们结合在一起时的功能。 .SECONDARY 功能&#xff1a;.SECONDARY 是一个特殊的伪目标&#xff0c;用于告诉 make 保留所有中间目标文件…...

金仓数据库KCM认证考试介绍【2025年4月更新】

KCM&#xff08;金仓认证大师&#xff09;认证是金仓KES数据库的顶级认证&#xff0c;学员需通过前置KCA、KCP认证才能考KCM认证。 KCM培训考试一般1-2个月一次&#xff0c;KCM报名费原价为1.8万&#xff0c;当前优惠价格是1万&#xff08;趋势是&#xff1a;费用越来越高&…...

在 macOS 上安装和配置 Aria2 的详细步骤

在 macOS 上安装和配置 Aria2 的详细步骤&#xff1a; 1.安装 Aria2 方式一&#xff1a;使用 Homebrew Homebrew 是 macOS 上的包管理器&#xff0c;可以方便地安装和管理软件包。 • 打开终端。 • 输入以下命令安装 Aria2&#xff1a; brew install aria2• 检查安装是否…...

如何通过句块训练法(Chunks)提升英语口语

真正说一口流利英语的人&#xff0c;并不是会造句的人&#xff0c;而是擅长“调取句块”的人。下面我们从原理、方法、场景、资源几个维度展开&#xff0c;告诉你怎么用“句块训练法&#xff08;Chunks&#xff09;”快速提升英语口语&#xff1a; 一、什么是“句块”&#xff…...