• C++ Tutorials: C++ Language: Other language features: Exceptions


    C++官方参考链接:Exceptions - C++ Tutorials (cplusplus.com)

    异常
    异常通过将转移控制到称为处理程序的特殊函数,提供了一种对程序中的异常情况(如运行时错误)做出反应的方法。 
    为了捕获异常,将一部分代码置于异常检查之下。这是通过将这部分代码封装在一个try块中实现的。当该块中出现异常情况时,将抛出异常,将控制转移到异常处理程序。如果没有抛出异常,代码将正常继续,并忽略所有处理程序
    从try块内部使用throw关键字抛出异常异常处理程序是用关键字catch声明的,它必须放在try块后面
    // exceptions
    #include
    using namespace std;

    int main () {
      try
      {
        throw 20;
      }
      catch (int e)
      {
        cout << "An exception occurred. Exception Nr. " << e << '\n';
      }
      return 0;

    异常处理下的代码包含在try块中。在这个例子中,这段代码抛出了一个异常:
    throw 20;
    throw表达式接受一个形参(在本例中为整数值20),20作为实参传递给异常处理程序。 
    异常处理程序在try块的闭括号后面用catch关键字声明。catch的语法类似于只有一个形参的普通函数。这个形参的类型非常重要,因为throw表达式传递的实参的类型要对照它进行检查,只有在它们匹配的情况下,异常才会被该处理程序捕获
    多个处理程序(即catch表达式)可以被链接;每一个都有不同的形参类型。只有其实参类型与throw语句中指定的异常类型相匹配的处理程序才会被执行。
    如果使用省略号(...)作为catch的形参,那么无论抛出的异常是什么类型,该处理程序都将捕获任何异常。这可以作为一个默认的处理程序来捕获所有没有被其他处理程序捕获的异常:
    try {
      // code here
    }
    catch (int param) { cout << "int exception"; }
    catch (char param) { cout << "char exception"; }
    catch (...) { cout << "default exception"; }
    在这种情况下,最后一个处理程序将捕获任何既不是int也不是char类型的异常。
    在程序处理了异常之后,在try-catch块之后恢复执行,而不是在throw语句后!
    也可以在更多的外部try块中嵌套try-catch块。在这些情况下,我们有可能内部catch块将异常转发到它的外部级别。这是通过表达式throw完成的;不带实参。例如:
    try {
      try {
          // code here
      }
      catch (int n) {
          throw;
      }
    }
    catch (...) {
      cout << "Exception occurred";

    异常规范
    较旧的代码可能包含动态异常规范。它们现在在C++中已被弃用,但仍受支持。动态异常规范紧跟在函数的声明之后,并向其追加throw说明符。例如: 

    double myfunction (char param) throw (int);
    这声明了一个名为myfunction的函数,它接受一个char类型的实参并返回一个double类型的值。如果此函数抛出了非int类型的异常,则该函数调用std::unexpected,而不是查找处理程序或调用std::terminate
    如果这个throw说明符为空,没有任何类型,这意味着对于任何异常都将调用std::unexpected。没有throw说明符的函数(普通函数)从不调用std::unexpected,而是遵循查找异常处理程序的正常路径。
    int myfunction (int param) throw(); // all exceptions call unexpected
    int myfunction (int param);         // normal exception handling 

    标准异常
    C++标准库提供了一个基类,专门用于声明要作为异常抛出的对象。它被称为std::exception,在头文件中定义。该类有一个名为what虚成员函数,它返回一个以空结束的字符序列(类型为char *),可以在派生类中重写该序列,以包含异常的某种描述。
    // using standard exceptions
    #include
    #include
    using namespace std;

    class myexception: public exception
    {
      virtual const char* what() const throw()
      {
        return "My exception happened";
      }
    } myex;

    int main () {
      try
      {
        throw myex;
      }
      catch (exception& e)
      {
        cout << e.what() << '\n';
      }
      return 0;
    }

    我们已经放置了一个通过引用捕获异常对象的处理程序(注意类型后面的&号),因此它也捕获从exception派生的类,比如类型为myexception的myex对象。
    C++标准库组件抛出的所有异常都会抛出派生自此exception类的异常。这些都是: 

    exception(异常)description(描述)
    bad_allocthrown by new on allocation failure(由分配失败的new抛出)
    bad_castthrown by dynamic_cast when it fails in a dynamic cast(在动态强制转换中失败时,由dynamic_cast抛出)
    bad_exceptionthrown by certain dynamic exception specifiers(由某些动态异常说明符抛出)
    bad_typeidthrown by typeid(由typeid抛出)
    bad_function_callthrown by empty function objects(由空函数(function)对象抛出)
    bad_weak_ptrthrown by shared_ptr when passed a bad weak_ptr

    同样派生自exception,头文件定义了两种通用异常类型,可由自定义异常继承以报告错误:

    exception(异常)description(描述)
    logic_errorerror related to the internal logic of the program(程序内部逻辑相关的错误)
    runtime_errorerror detected during runtime(运行时检测到的错误)

    需要检查标准异常的典型例子是内存分配:
    // bad_alloc standard exception
    #include
    #include
    using namespace std;

    int main () {
      try
      {
        int* myarray= new int[1000];
      }
      catch (exception& e)
      {
        cout << "Standard exception: " << e.what() << endl;
      }
      return 0;
    }

    在本例中,异常处理程序可能捕获的异常是bad_alloc。因为bad_alloc派生自标准基类exception,所以它可以被捕获(通过引用捕获,捕获所有相关类)。 

  • 相关阅读:
    【Java进阶】泛型和多线程
    数据结构——分块查找
    DHorse系列文章之操作手册
    计算机视觉+人工智能面试笔试总结——使用CNN进行图像分类
    音视频中文件的复用和解复用
    SaaS系统为何一直不被信赖
    u盘制成系统盘之后如何让恢复普通盘
    Windows之应用安装程序 —— winget
    【CV】第 4 章:图像深度学习
    【高性能计算是如何变现的?】
  • 原文地址:https://blog.csdn.net/weixin_40186813/article/details/126915269