C++面向对象(OOP)编程-异常机制

本文主要介绍C++异常的处理,异常的种类,以及如何自己实现异常,以及异常常见的面试题。

目录

1 异常介绍

2 异常处理

2.1 抛出异常

2.2 捕获异常

2.3 自定义异常

3 异常使用原则

4 异常处理模式

5 stdexcept 中的异常类

6 异常机制面试问题

6.1 什么是C++中的异常处理机制?它的作用是什么?

6.2 如何抛出异常和捕获异常?请给出一个示例。

6.3 如果需要实现自己的异常,应该怎么做?

6.4 请简述C++中的异常类层次结构,并说明它们的作用

6.5 在使用异常处理时,有哪些需要注意的事项?

6.6 什么是异常安全性?如何保证程序具有异常安全性?

6.7 如果一个函数可能抛出多种类型的异常,应该如何进行捕获?

6.8 在C++11中新增了一种异常处理机制,即std::exception_ptr。请简述它的作用和使用方法。


1 异常介绍

        异常是指在程序运行过程中,由于系统条件、操作不当等原因而引起的运行错误。

常见的异常包括:除零错误、指针访问受保护空间、数据越界、分配空间失败、要打开的文件不存在等。

     C++异常处理使用关键字trycatchthrow来实现。

  1. try块:用于包含可能会抛出异常的代码。当异常被抛出时,程序会立即停止执行try块中的剩余代码,并将控制权转移到与该异常匹配的catch块。

  2. catch块:用于捕获并处理异常。每个catch块都指定了要捕获的异常类型。当异常与某个catch块匹配时,程序将执行该块中的代码来处理异常。

  3. throw语句:用于显式地抛出一个异常对象。可以使用throw语句手动触发异常,或者在程序中遇到错误时自动抛出异常。

2 异常处理

2.1 抛出异常

        使用throw来主动抛出异常,程序运行错误也会主动抛出异常。

一个例子:

void func(int x) {if (x < 0) {throw std::invalid_argument("x不能为负数");}
}

        当输入的值小于0时,抛出一个异常对象,然后可以利用try{}catch{}来捕获。

2.2 捕获异常

        当程序执行到throw语句时,会跳转到最近的catch语句块处理异常。catch语句块中包含了捕获异常后要执行的代码。

一个例子:

try {func(x);
} catch (std::exception& e) {// 处理异常
}

 上述例子使用try来检测异常,看func函数是否会抛出异常,如果抛出std::exception异常,就会跳转到catch语句块中进行处理。

如果内部抛出的double,则这里的std::exception&就要写为double。

2.3 自定义异常

        实现自己的异常,可以通过继承标准库中的异常类,来实现自己的异常。一般,我们需要重写exception类中的what()方法,以提供更详细的异常信息。

一个例子:

#include <iostream>
#include <exception>// 自定义异常类
class MyException : public std::exception
{public:MyException(const char* message) : msg_(message) {}const char* what() const noexcept override {return msg_;}private:const char* msg_;
};int main() {try {throw MyException("这是一个自定义异常");} catch (const MyException& e) {std::cerr << "捕获到自定义异常: " << e.what() << std::endl;}return 0;
}

        运行结果:

上述代码描述了一个继承自标准库中的exception类,重写what方法的自定义异常类。

3 异常使用原则

        (1)异常处理只是一种容错机制,不能用来代替正常的程序代码逻辑。

        (2)不要滥用异常处理,应该只在必要的情况下使用。

        (3)应该尽可能提供详细的异常信息,以方便调试和定位问题。

        (4)在捕获异常时,应该考虑到可能发生的所有异常情况,并分别进行处理。

        (5)对于一个检测会有多种异常,我们可以使用多个catch来捕获。

一个例子:

try{        //异常检测throw  异常类型1对应的异常值;  //抛出异常:异常值或异常对象}
catch (异常类型1)                     //捕获异常
{// 进行异常处理的语句}
catch (异常类型2)
{//进行异常处理的语句}

上述形式可以抛出多个类型的异常。

4 异常处理模式

        异常处理模式——指处理完异常后,程序的执行流程。默认的异常处理模式为终止模式。

终止模式——指异常抛出后,将退出导致异常的子程序或结构,转而去执行捕捉异常的catch块,catch块执行完毕后也不会再返回到抛出异常的位置,也就是说throw 后的数据不会再执行。

一个例子:

#include <iostream>
#include <exception>// 自定义异常类
class MyException : public std::exception
{public:MyException(const char* message) : msg_(message) {}const char* what() const noexcept override {return msg_;}private:const char* msg_;
};void test_exp()
{std::cout << "throw before!" << std::endl;throw MyException("这是一个自定义的测试异常!");std::cout << " throw after!" << std::endl; 
}int main() {try {std::cout << "异常的检测!" << std::endl;test_exp();} catch (const MyException& e) {std::cerr << "捕获到自定义异常: " << e.what() << std::endl;}return 0;
}

        运行结果:

        由上述得知,main函数执行后,首先执行try中程序,调用throw抛出异常,此时不会执行抛出异常后的代码,会直接跳转到执行catch程序块,执行后续的代码。

        因此throw后面不能放有效的代码。

5 stdexcept 中的异常类

        `stdexcept` 是 C++ 标准库中的一个头文件,它定义了一些用于表示异常情况的类。以下是         `stdexcept` 中的主要异常类:

        (1) `logic_error`:逻辑错误,通常是由于程序中的逻辑错误导致的异常。
        (2)`invalid_argument`:无效参数,当函数接收到无效参数时抛出。
        (3)`runtime_error`:运行时错误,通常是由于程序中的运行时错误导致的异常。
        (4)`domain_error`:域错误,当函数接收到超出有效范围的值时抛出。
        (5)`length_error`:长度错误,当请求的长度超出了有效范围时抛出。
        (6)`out_of_range`:范围错误,当操作数超出有效范围时抛出。
        (7)`overflow_error`:溢出错误,当算术运算导致溢出时抛出。
        (8)`underflow_error`:下溢错误,当算术运算导致下溢时抛出。
        (9)`system_error`:系统错误,当发生操作系统相关的错误时抛出。
        (10)`ios_base::failure`:I/O 失败,当 I/O 操作失败时抛出。
        (11)`bad_alloc`:内存分配失败,当无法分配所需内存时抛出。

        异常类层次:

标准异常类层次
标准异常类层次

6 异常机制面试问题

6.1 什么是C++中的异常处理机制?它的作用是什么?

        C++中的异常处理机制是一种错误处理机制,可以帮助我们处理程序在运行时可能会遇到的异常情况,比如内存分配错误、文件打开失败等。当程序运行到某一处出现异常时,程序会立即跳转到相应的异常处理代码。

        其主要作用在于:在程序运行时,发生异常后能够快速地定位并处理问题,从而保证程序的稳定性和正确性。

6.2 如何抛出异常和捕获异常?请给出一个示例。

#include <iostream>
#include <exception>int main(int argc, char *argv[])
{try{throw std::runtime_error(" 这是一个异常的检测!");}catch(std::exception & e){std::cout << e.what() << std::endl;}return 0;
}

6.3 如果需要实现自己的异常,应该怎么做?

        继承标准库中的expection类,重写其中的what方法。

一个例子:
 

#include <iostream>
#include <exception>
#include <stdexcept>// 自定义异常类
class MyException : public std::exception
{public:MyException(const char* message) : msg_(message) {}const char* what() const noexcept override {return msg_;}private:const char* msg_;
};void test_exp()
{std::cout << "throw before!" << std::endl;throw MyException("这是一个自定义的测试异常!");std::cout << " throw after!" << std::endl; 
}int main() {try {std::cout << "异常的检测!" << std::endl;test_exp();} catch (const MyException& e) {std::cerr << "捕获到自定义异常: " << e.what() << std::endl;}return 0;
}

6.4 请简述C++中的异常类层次结构,并说明它们的作用

        td::exception:所有标准异常类的基类,包含了一些通用的异常信息。
        std::bad_alloc:内存分配错误时抛出的异常。
        std::logic_error:内部逻辑错误时抛出的异常,例如无效参数或操作。
        std::runtime_error:运行时错误时抛出的异常,例如文件打开失败等。
这些异常类都包含了一个what()方法,返回一个描述异常信息的字符串。我们可以通过继承这些异常类来实现自己的异常。

6.5 在使用异常处理时,有哪些需要注意的事项?

在使用异常处理时,我们需要注意以下几点:

  • 异常处理只是一种容错机制,不能用来代替正常的程序代码逻辑。

  • 不要滥用异常处理,应该只在必要的情况下使用。

  • 应该尽可能提供详细的异常信息,以方便调试和定位问题。

  • 在捕获异常时,应该考虑到可能发生的所有异常情况,并分别进行处理。

6.6 什么是异常安全性?如何保证程序具有异常安全性?

        异常安全性是指程序在发生异常后能够正确地进行资源回收。保证程序具有异常安全性可以避免内存泄漏等问题。

通常情况下,我们可以通过RAII(Resource Acquisition Is Initialization)技术来保证程序具有异常安全性。RAII技术利用对象的生命周期来管理资源的分配和释放,将资源的分配和释放过程封装在类的构造函数和析构函数中。

        请解释以下关键字的含义:try、catch、throw、noexcept。

  • try:用于包含可能抛出异常的代码块。

  • catch:用于捕获并处理异常的代码块。

  • throw:用于抛出一个异常,并跳转到最近的catch语句块。

  • noexcept:指示一个函数不会抛出任何异常。

6.7 如果一个函数可能抛出多种类型的异常,应该如何进行捕获?

        如果一个函数可能抛出多种类型的异常,我们可以使用多个catch语句块来分别捕获这些异常。catch语句块的顺序应该从具体到一般,以确保所有异常都能够被正确地捕获。

6.8 在C++11中新增了一种异常处理机制,即std::exception_ptr。请简述它的作用和使用方法。

        std::exception_ptr是C++11中新增的一种异常处理机制,可以用来保存当前正在处理的异常,并在稍后的时间点重新抛出该异常。

一个例子:

void func() {try {// 可能会抛出异常的代码} catch (...) {std::exception_ptr p = std::current_exception();// 处理异常std::rethrow_exception(p);}
}int main() {try {func();} catch (std::exception& e) {std::cout << e.what() << std::endl;}return 0;
}

在上面的示例中,如果func函数抛出了异常,就会跳转到catch语句块中处理异常,并使用std::current_exception()函数获取当前正在处理的异常,然后使用std::rethrow_exception()函数重新抛出该异常。在main函数中,我们再次捕获这个异常并进行处理。
 

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

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

相关文章

window10下载与安装zookeeper,图文说明

1&#xff0c;下载 打开连接 &#xff1b;https://downloads.apache.org/zookeeper/ 选择版本下载 2&#xff0c;解压 cmd黑窗口解压命令 tar -zxvf apache-zookeeper-3.8.3-bin3&#xff0c;修改配置 复制zoo_sample.cfg&#xff0c;重命名为zoo.cfg zoo.cfg配置 # The …

最新AI创作系统ChatGPT系统源码+DALL-E3文生图+支持AI绘画+GPT语音对话功能

一、AI创作系统 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI…

Vue 项目中使用 debugger 在 chrome 谷歌浏览器中失效以及 console.log 指向去了 vue.js 代码

问题 今天在代码里面输出 console.log 信息直接指向了 vue.js&#xff0c;并且代码里面写了 debgger 也不生效 解决 f12 找到浏览器的这个设置图标 找到这个 ignore list 的 custom exclusion rules 取消掉 /node_modules/|/bower_components/ 这样就正常了

Linux--学习记录(3)

G重要编译参数 -g&#xff08;GDB调试&#xff09; -g选项告诉gcc产生能被GNU调试器GDB使用的调试信息&#xff0c;以调试程序编译带调试信息的可执行文件g -g hello.c -o hello编译过程&#xff1a; -E&#xff08;预处理&#xff09; g -E hello.c -o hello.i-S&#xff08;编…

PHPStorm一站式配置

phpstorm安装好之后&#xff0c;先别急着编码。工欲善其事&#xff0c;必先利其器&#xff0c;配置好下面这些之后让编码事半功倍。 主题 Appearance & Behavior -> Appearance -> Theme 选中 [Light with Light Header] 亮色较为护眼 关闭更新 Appearance & …

数据分析思维导图

参考&#xff1a; https://zhuanlan.zhihu.com/p/567761684?utm_id0 1、数据分析步骤地图 2、数据分析基础知识地图 3、数据分析技术知识地图 4、数据分析业务流程 5、数据分析师能力体系 6、数据分析思路体系 7、电商数据分析核心主题 8、数据科学技能书知识地图 9、数据挖掘…

Postman教程总结-新建一个测试案例

1.创建一个文件夹&#xff1b;文件夹的名字最好用自己项目的名字命名方便使用和维护

SVN小白常见操作流程

SVN小白常见操作流程 一、什么是Subversion&#xff1f;二、TortoiseSVN客户端安装教程三、SVN 操作3.1 SVN Ckeckout(检出)3.2 Add(新增文件)3.3 SVN Commit(提交)3.4 SVN Update(更新操作)3.5SVN Delete(删除操作)3.6 SVN Revert to a revision(版本回溯)3.7 不同版本内容之间…

JAVA:深入探讨Java 8 Stream的强大功能与用法

1、简述 Java 8引入了Stream API&#xff0c;为处理集合数据提供了一种更为强大和灵活的方式。Stream是一种抽象的数据结构&#xff0c;它允许你以一种声明性的方式处理数据集合。与传统的集合操作不同&#xff0c;Stream并不是一个存储数据的数据结构&#xff0c;而是在源数据…

GCS轨迹优化算法:有效提升机器人在复杂环境下的行动能力

原创 | 文 BFT机器人 机器人要在迷宫中找到出路并非易事&#xff0c;试想我们让机器人穿越一个孩子的游戏室&#xff0c;散落在地板上的各种玩具和各类家具挡住了一些潜在的路径。这个混乱的”迷宫“要求机器人在不与任何障碍物相撞的情况下计算到达目的地的最优路径&#xff…

【C Primer Plus第六版 学习笔记】第十一章 字符串和字符串函数

有基础&#xff0c;进阶用&#xff0c;个人查漏补缺 puts()只显示字符串&#xff0c;而且自动在末尾加上换行符 字符串定义&#xff08;字符串有字符串常量、char类型数组、指向char的指针&#xff09; 字符串常量&#xff1a; 用双括号括起来&#xff0c;双引号中的字符和编译…

数据加密标准DES硬件实现(Modelsim)

数据加密标准DES硬件实现 本文内容摘要理论依据和设计内容仿真结果整体代码 本文内容摘要 本文设计并验证了DES的密钥扩展通路&#xff0c;分别采用Round Based方法和Pipeline方法两种方式设计并验证DES的明文通路 理论依据和设计内容 首先&#xff0c;要了解分组密码算法及DE…