【037】从异常到优雅的错误处理:揭秘C++异常机制的神奇力量

您所在的位置:网站首页 js抛出异常语句 【037】从异常到优雅的错误处理:揭秘C++异常机制的神奇力量

【037】从异常到优雅的错误处理:揭秘C++异常机制的神奇力量

2023-07-10 02:04| 来源: 网络整理| 查看: 265

揭秘C++异常机制的神奇力量 引言一、异常的基本概念二、异常的抛出和捕获三、栈解旋四、异常的接口声明五、异常变量的生命周期六、异常的多态七、C++标准异常八、编写自己的异常总结

引言

💡 作者简介:一个热爱分享高性能服务器后台开发知识的博主,目标是通过理论与代码实践的结合,让世界上看似难以掌握的技术变得易于理解与掌握。技能涵盖了多个领域,包括C/C++、Linux、Nginx、MySQL、Redis、fastdfs、kafka、Docker、TCP/IP、协程、DPDK等。 👉 🎖️ CSDN实力新星、CSDN博客专家 👉 🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。 👉 🔔 专栏地址:C++从零开始到精通 👉 🔔 博客主页:https://blog.csdn.net/Long_xu

🔔 上一篇:【036】读懂C++的强制类型转换static_cast、const_cast、dynamic_cast以及reinterpret_cast

一、异常的基本概念

C++异常机制是一种处理程序运行时错误的机制。当程序在运行过程中发生异常情况,比如除零错误、内存访问错误、数组下标越界、读取的文件不存在、空指针、内存不足、访问非法内存或者其他不可预测的错误,程序可以抛出一个异常,然后通过异常处理机制来捕获和处理这个异常。遇到错误,抛出异常、捕获异常。

异常由"throw"语句抛出,可以是任意的数据类型,通常是派生自std::exception类的异常对象。异常对象可以携带有关异常的信息,比如错误的原因、位置等。异常是一个类。

异常的处理是通过"try-catch"语句块来实现的。"try"块用于包含可能抛出异常的代码,当异常发生时,程序会跳转到与之对应的"catch"块,并执行相关的异常处理代码。"catch"块用于捕获和处理特定类型的异常。

如果一个异常在"try"块中没有被捕获到,它会继续向上层调用栈传播,直到找到匹配的"catch"块或者到达程序的顶层,如果没有处理的"catch"块,程序会终止并引发一个未处理异常的错误。

在处理异常时,可以使用多个"catch"块来捕获不同类型的异常,并根据需要进行相应的处理。此外,还可以使用"finally"块来执行无论是否发生异常都必须执行的代码,比如资源的释放等。

C++异常机制提供了一种结构化的方式来处理程序运行时的错误,使得代码更加可读、可维护,并提供了一种灵活的错误处理机制。

C++异常机制相比C语言异常处理的优势:

函数的返回值可以忽略,但是异常不可以忽略。如果忽略异常将导致程序退出。函数的返回值没有任何语义信息,而异常却包含语义信息。有时从类名就能够体现出来。 二、异常的抛出和捕获

C++异常的抛出和捕获是通过使用"throw"和"try-catch"语句来实现的。

语法:

try{ throw 异常值; } catch(异常类型1 异常值1) { // 处理异常的代码 } catch(异常类型2 异常值2) { // 处理异常的代码 } catch(...)// 任何异常都捕获 { // 处理异常的代码 }

异常的抛出: 使用"throw"语句可以在程序的某个地方抛出异常。"throw"语句后面可以跟一个异常对象,该对象可以是任意类型,通常从std::exception派生而来。

例如,我们可以这样抛出一个整型异常:

int numerator = 10; int denominator = 0; if (denominator == 0) { throw 100; // 抛出一个整型异常 }

异常的捕获: 使用"try-catch"语句可以捕获并处理异常。在"try"块中包含可能抛出异常的代码,当异常发生时,程序会跳转到与之对应的"catch"块,并执行相关的异常处理代码。

例如,我们可以这样捕获并处理前面抛出的整型异常:

try { // 可能抛出异常的代码 int result = numerator / denominator; } catch (int e) { // 捕获整型异常 // 处理异常的代码 std::cout // 捕获任意类型的异常 // 处理异常的代码 }

在"catch"块中,可以执行相应的异常处理代码,比如输出错误信息、进行日志记录、回滚操作等。

异常的捕获可以嵌套使用,即在一个"catch"块中再次使用"try-catch"语句来捕获更深层次的异常。

try { // 可能抛出异常的代码 } catch (int e) { try { // 进一步处理异常的代码 } catch (...) { // 捕获更深层次的异常并处理 } }

最后,如果异常在整个调用栈中没有被捕获到,程序会终止并引发一个未处理异常的错误。因此,在使用异常处理机制时,要确保所有可能的异常都能够被适当地捕获和处理。

示例:

#include using namespace std; int main() { try { //throw 1; //throw 'c'; throw 3.14f; } catch(int e){ cout cout data = num; cout try { Data ob1(100); Data ob2(200); Data ob3(300); throw 3.14f; } catch(int e){ cout cout throw 1; throw 'c'; //throw "hello";//抛出,不能捕获。 }

(3)不能抛出任何异常;在函数右边使用throw()修饰。

void test() throw() { //throw "hello";//不能抛出异常 //throw 1; //throw 'c'; } 五、异常变量的生命周期

定义一个这样的异常变量类:

class MyException{ public: MyException(){ cout cout cout cout throw MyException(); } catch (MyException e)//普通对象接异常,发生拷贝构造 { cout public: MyException() { cout cout throw new MyException; } catch (MyException *e)//普通对象接异常,发生拷贝构造 { cout public: MyException() { cout cout throw MyException(); } catch (MyException &e)//普通对象接异常,发生拷贝构造 { cout public: virtual void printError() = 0; }; // 空指针异常 class NullPointerException :public BaseException { public: virtual void printError() { cout cout try { test(); } catch (BaseException& e)// 父类引用,可以捕获该父类派生出的所有子类的异常 { e.printError(); } return 0; } 七、C++标准异常

C++的所有异常都是由exception派生的;所有的异常捕获都是使用父类去捕获的。C++标准库异常继承层次图: 在这里插入图片描述

异常名称描述exception所有标准异常类的父类bad_alloc当operator new and operator new[],请求分配内存失败时bad_exception这是个特殊的异常,如果函数的异常抛出列表里声明了badexception异常,当函数内部抛出了异常抛出列表中没有的异常,这时调用的unexpected函数中抛出异常,不论什么类型,都会被替换成为badexception类型。bad_typeid使用typeid操作符,操作一个NULL指针,而该指针是带有虚函数的类,这时抛出这个异常。bad_cast使用dynamic_cast转换引用失败的时候。ios_base::failureio操作过程出现错误。logic_error逻辑错误,可以在运行前检测的错误。runtime_error运行时错误,仅在运行时才能检测的错误

logic_error的子类:

子类描述std::invalid_argument表示传递给函数的参数无效。std::domain_error表示一个函数或方法在一个无效的数学域(domain)上被调用。std::length_error表示一个操作尝试超出有效范围的长度。std::out_of_range表示一个索引或下标超出有效范围。std::overflow_error表示一个算术运算结果超出了所能表示的最大值。std::underflow_error表示一个算术运算结果超出了所能表示的最小值。

runtime_error的子类:

子类描述std::runtime_error表示一般的运行时错误。std::range_error表示一个值超出了有效范围。std::overflow_error表示一个算术运算结果超出了所能表示的最大值。std::underflow_error表示一个算术运算结果超出了所能表示的最小值。std::logic_error表示逻辑错误。通常不被直接使用作为子类,但可以用于表示未被其他子类覆盖的运行时错误。std::bad_alloc表示内存分配失败。std::bad_cast表示类型转换失败。std::bad_typeid表示typeid运算符在多态类型中失败。std::bad_exception表示在异常处理过程中发生了无法处理的异常。

示例:

#include using namespace std; int main() { try { throw out_of_range("我越界啦!!!"); } catch (exception &e) { // waht()存放的是异常信息,以char*形式。 cout } NewException(string msg) { str = msg; } // 重写父类的waht() virtual const char *what() const throw()//防止父类在子类前抛出标准异常 { return str.c_str(); } ~NewException() {} }; int main() { try { throw NewException("这是自己的异常"); } catch (exception &e) { // waht()存放的是异常信息,以char*形式。 cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3