c++中的try-catch及throw

news/2024/11/7 0:59:17/文章来源:https://www.cnblogs.com/hisun9/p/18531351

C++ 使用 try-catch 语句来捕获和处理异常。try 块包含可能发生错误的代码,而 catch 块则用来捕获并处理错误。

try-catch 语句的基本结构

try {// 可能抛出异常的代码
} catch (exception_type1 e1) {// 处理异常类型 1
} catch (exception_type2 e2) {// 处理异常类型 2
} catch (...) {// 捕获所有类型的异常
}

具体解释:

  1. try 块

    try 块包含可能发生异常的代码。

    如果 try 块中的代码发生了异常,程序会跳转到相应的 catch 块进行异常处理。

  2. catch 块

    catch 用来捕获由 try 块抛出的异常,并进行处理。

    可以有多个 catch 块,每个 catch 块负责处理特定类型的异常。

    如果 catch 中的异常类型与抛出的异常类型匹配,程序会执行该 catch 块中的代码。

  3. catch (...)

    catch(...) 是一个通配符,用来捕获所有类型的异常。

    这在无法确定抛出异常的具体类型时特别有用

举两个例子说明

  1. 第一个例子

    #include <iostream>
    using namespace std;int main() {try {int a = 5;int b = 0;if (b == 0) {throw "Division by zero error!";}cout << a / b << endl;} catch (const char* e) {cout << "Error: " << e << endl;  // 捕获并处理除零错误}return 0;
    }
    

    输出如下:

    img

    解释:

    在 try 块中,程序尝试执行可能出错的代码。

    如果发生异常(这里是通过 throw 手动抛出除零错误),catch 块会捕获到异常并进行处理。

  • 第二个例子

    #include <iostream>
    #include <stdexcept>  // 包含异常类using namespace std;int main() {try {int a = 10, b = 0;if (b == 0) {throw std::runtime_error("Division by zero error!"); // 抛出运行时错误}cout << a / b << endl;} catch (const std::runtime_error& e) {cout << "Caught a runtime error: " << e.what() << endl;  // 捕获并处理 std::runtime_error} catch (const std::exception& e) {cout << "Caught a general exception: " << e.what() << endl;  // 捕获所有 std::exception 类型的异常} catch (...) {cout << "Caught an unknown error!" << endl;  // 捕获其他所有类型的异常}return 0;
    }
    

    输出如下:

    img

    解释:

    try 块中的代码试图执行可能会抛出异常的操作。例如,在这个例子中,我们故意将 b 设置为 0,模拟除零错误。

    如果程序遇到除零错误,抛出一个 std::runtime_error 类型的异常。

    catch (const std::runtime_error& e) 块捕获 std::runtime_error 类型的异常,并输出错误信息。

    catch (const std::exception& e) 是更广泛的异常类型,它会捕获所有继承自 std::exception 类的异常(包括 std::runtime_error)。

    catch (...) 捕获所有其他类型的异常,确保即使没有明确处理某种异常类型,程序也不会崩溃。

throw 语句:抛出异常

在 C++ 中,throw 关键字用于抛出异常。可以在任何地方抛出异常,通常是在遇到错误或不符合预期的条件时。

throw some_exception;  // 抛出一个异常

常见的异常类型

C++ 标准库定义了几种常见的异常类型。可以选择抛出这些异常类型之一,或者创建自己的异常类。

  • std::exception:这是所有标准异常类的基类,所有其他标准异常类都继承自它。

  • std::runtime_error:运行时错误,表示程序运行时发生的错误。

  • std::logic_error:逻辑错误,表示程序的逻辑上有问题,比如越界访问数组等。

  • std::out_of_range:越界错误,通常用于容器类(如 std::vector)访问越界元素时抛出的异常。

  • std::invalid_argument:无效参数错误,表示传递给函数的参数不合法。

  • std::bad_alloc:内存分配错误,当 new 操作失败时抛出此异常。

自定义异常类

也可以创建自己的异常类,继承自 std::exception 或其派生类,以便在程序中抛出和捕获特定类型的异常。

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

输出如下:

img

异常的传播和处理

当 throw 抛出异常时,异常会沿着调用栈向上传递,直到找到一个匹配的 catch 块。

如果没有合适的 catch 块捕获异常,程序会终止并显示未处理的异常信息。

比如:

#include <iostream>
#include <stdexcept>  // 包含标准异常类型using namespace std;int main() {try {cout << "Throwing an exception..." << endl;throw std::runtime_error("This is a runtime error!");  // 抛出一个运行时错误}// 这里只捕获 std::logic_error 类型的异常,忽略 std::runtime_errorcatch (const std::logic_error& e) {cout << "Caught logic_error: " << e.what() << endl;}cout << "This will not be printed if an exception is thrown!" << endl;return 0;
}

输出如下:

img

异常处理的注意事项

异常的安全性:捕获异常时要确保程序的状态一致性。如果在 catch 块中处理异常时发生了额外的错误,可能导致程序不稳定。

性能问题:异常处理会增加程序的运行时开销,尤其是在频繁抛出和捕获异常的情况下。因此,异常处理应该只用于真正的错误,而不是正常的程序流控制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/827959.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【windows应用】windows系统怎么查看密钥

原创 L.w IT小农工大家都知道,安装Win10/11系统之后需要密钥才能使用所有的功能,网上提供的激活方法有很多,那我们要怎么知道自己的密钥呢? Windows 产品密钥是由 25 个字符组成的代码,用于激活 Windows。其格式如下所示: 产品密钥:XXXXX-XXXXX-XXXXX-XXXXX-XXXXX 操作过…

【 js编程】原型和原型链

原创 mike Web全栈开发者驿站原型和原型链在 js中起着至关重要的作用。它们使得 js 能够以一种独特的方式实现面向对象编程,虽然与传统的面向对象编程语言有所不同,但却提供了很大的灵活性和强大的功能。然而,原型链也有一些缺点,如属性查找的性能问题、继承的脆弱性以及隐…

全网最适合入门的面向对象编程教程:58 Python字符串与序列化-序列化Web对象的定义与实现

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML\YAML\JSON格式这种序列化Web对象。这种序列化Web对象容易与其他程序设计语言交互,可读性强,容易被传递给其它系统或客户端。全网最适合入门的面向对象编程教程:58 Python 字符串与序列化-序…

开源低代码平台-Microi吾码-源码本地运行-后端

开源低代码平台-Microi吾码-简介技术框架:.NET8 + Redis + MySql/SqlServer/Oracle + Vue2/3 + Element-UI/Element-Plus 平台始于2014年(基于Avalon.js),2018年使用Vue重构,于2024年10月29日开源 试用地址:https://microi.net Gitee开源地址:https://gitee.com/ITdos/m…

CAPL基础

CAPL基础 1.CAPL如何生效 CAPL通过在Simulation Setup窗口设置CAPL节点,并加载对应的CAPL文件使CAPL生效。 2.Event驱动 CAPL语言的运行逻辑是事件触发,当满足条件时执行对应的代码 如下图所示有启动触发、停止触发、发送报文触发、定时器触发和按键触发等3.报文发送 1.自定义…

开源 - Ideal库 - 常用时间转换扩展方法(一)

分享《开源-Ideal库》系列文章,含公共、文档等库封装,首篇介绍时间转换封装,包括日期时间、时间戳与字符串间转换方法,后续上传至Nuget,测试代码已上传至代码库。从事软件开发这么多年,平时也积累了一些方便自己快速开发的帮助类,一直在想着以什么方式分享出来,因此有了…

excel排序

目录Excel成绩排名的两种方法方法一:先排序,再填排名 Excel成绩排名的两种方法 方法一:先排序,再填排名 具体步骤如下:先左键选中要排序的区域,如下图右键,然后选择排序->自定义排序选择要排序的区域(注意勾选数据包含标题)​ 数据包含标题的意思就是,上面的姓名、…

千锋Linux云计算-文件权限管理

掌握基本权限ugo的命令(chmod、chown),列举2条设置权限命令并解释每个单词含义。 掌握基本权限acl的命令(setfacl、getfacl),列举2条设置权限命令并解释每个单词含义。 了解特殊权限含义(suid、chattr、umask),列举2条设置权限命令并解释每个单词含义。1. 设置传统权…

静态路由规则配置

静态路由配置 本质上通过配置虚拟机实现不同网段之间进行通信 第一步:准备3台虚拟机第一台网卡配置NAT模式;第二台配置两个网卡,分别为配置NAT模式 + LAN区段;第三台配置LAN区段第二步:配置网卡相关信息先查看宿主机(物理机)VMnet8网卡的IP和子网掩码配置网卡相关信息【…

SpringBoot获取文件将要上传的IP地址

SpringBoot获取文件将要上传的IP地址说明: 有的项目会涉及文件上传,比如“更换logo业务”,或者“自定义任务上传脚本等业务”都会涉及上传,而有的项目上传成功后找不到上传地址,所以需要打印IP,方便用户知晓上传的精确地址,下面封装了一个IPv4 工具类(因为是拷贝现成代…

Linux 下搭建 Spark3 + Jupyter 环境

spark3 + pyspark + jupyter 环境搭建最近想着来玩一玩大数据, 前段时间集中过了一遍 java, 最近又看了一些基础的 scala, 我感觉吧, 我都不想学. 还是觉得用 sql, javascript, python 这种脚本语言操作起来顺手, 但这并不影响对这个大数据生态的理解和学习. 这里主要是来记录一…

LeetCode3264[K次乘运算后的最终数组I]

LeetCode3264[K次乘运算后的最终数组I]题目 链接 LeetCode3264[K次乘运算后的最终数组I] 详情实例 实例1实例2提示题解 思路 先找到最小值 然后对最小值进行操作 最后输出容器 代码 class Solution { public:int findVecMinNumIndex(vector<int> nums)//找出最小值的下标…