Tutorial Study Image

C++ 中的异常处理


2023年6月9日, Learn eTutorial
671

在运行 C++ 代码时,可能会发生各种类型的故障,包括由于不正确的输入或程序员的编码错误造成的故障。当出现问题时,C++ 通常会停止并生成错误消息。这在 C++ 中称为抛出异常(这将抛出错误)。

C++ 中的异常处理究竟是什么意思?

C++ 中的异常处理允许您处理运行时错误等不可预见的情况。因此,如果发生意外事件,程序的控制权将传递给处理程序,这些处理程序是特殊函数。

您将程序代码的某个部分置于异常检查之下,以捕获异常。try-catch 块包含代码的特定区域。

如果该代码区域内发生异常情况,则一定会抛出异常。程序随后会将控制权传递给异常处理程序。

如果没有出现异常情况,代码将正常运行。处理程序将不予考虑。

C++ 中为什么需要异常处理?

C++ 中的异常处理用于以下原因:

  • 您的错误处理代码将与您的常规代码分开。代码将更易于阅读和维护。
  • 函数可以灵活地处理任何异常。即使函数抛出多个异常,它也只会捕获某些异常。调用者负责处理未捕获的异常。

C++ 中异常处理的关键字

throw: 当程序遇到问题时,它会抛出异常。在程序中,throw 关键字促进了抛出操作。

catch: 为了处理异常,程序使用异常处理程序。它插入到程序中必须处理问题的部分。这是通过使用 catch 关键字实现的。

try: try 标识将调用特定异常的代码段。其后应放置一个或多个 catch 块。

假设一个代码块将抛出异常。通过使用 try-and-catch 关键字,将捕获异常。try/catch 块应放置在可能抛出异常的代码周围。此类代码称为受保护代码。

语法

这是 try/catch 的语法


try {
   // the protected code
} catch( Exception_Name exception1 ) {
   // catch block
} catch( Exception_Name exception2 ) {
   // catch block
} catch( Exception_Name exceptionN ) {
   // catch block
}

 

尽管我们只有一个 try 语句,但我们可以有多个 catch 语句。要捕获的异常有一个名称,它是 ExceptionName。您定义的用于引用异常的名称是 exception1、exception2 和 exceptionN。

C++ 中异常处理的示例

  1. 以下是一个基本的 C++ 异常处理示例。程序输出中描述了 try/catch 块的执行流程。

    C++ 示例展示了如何处理异常。

    
    #include <iostream>
    using namespace std;
    
    int main()
    {
    int x = -1;
    
    // Some code
    cout << "Before the try \n";
    try {
     cout << "Inside the try \n";
     if (x < 0)
     {
      throw x;
      cout << "After the throw (Never executed) \n";
     }
    }
    catch (int x ) {
     cout << "Exception Caught \n";
    }
    
    cout << "After catch (Will be executed) \n";
    return 0;
    }
    
     
    

    输出

    
    Before the try 
    Inside the try 
    Exception Caught 
    After catch (Will be executed)
    
    
  2. 为了捕获所有异常类型,有一个特殊的 catch 块,称为“catch-all”块,表示为 catch(...)。例如,在以下程序中,当抛出 int 作为异常时,catch(...) 块将运行,因为没有针对 int 的 catch 块。

    带有 catch-all 的示例程序

    
    #include <iostream>
    using namespace std;
    
    int main()
    {
     try {
     throw 10;
     }
     catch (char *excp) {
      cout << "Caught " << excp;
     }
     catch (...) {
      cout << "The Default Exception\n";
     }
     return 0;
    }
    
     
    

    输出

    
    The Default Exception
    
  3. 对于基本类型,没有隐式类型转换。例如,在以下程序中,“a”不会隐式转换为 int。

    
    #include <iostream>
    using namespace std;
    
    int main()
    {
     try {
     throw 'a';
     }
     catch (int x) {
      cout << "Caught " << x;
     }
     catch (...) {
      cout << " The Default Exception\n";
     }
     return 0;
    }
    
     
    

    输出

    
    The Default Exception
    
  4. 如果抛出异常但未在某处捕获,则程序会异常终止。例如,在下面的程序中抛出了一个 char,但未被 catch 块捕获。

    
    #include <iostream>
    using namespace std;
    
    int main()
    {
     try {
     throw 'a';
     }
     catch (int x) {
      cout << "Caught ";
     }
     return 0;
    }
    
     
    

    输出

    
    terminate called after throwing an instance of 'char'
    timeout: the monitored command dumped core
    
  5. 派生类异常之后应处理基类异常。

  6. C++ 库提供了一个标准异常类,它作为所有标准异常的根类,类似于 Java。标准库组件抛出的所有对象都继承自该类。因此,通过捕获此类型,可以捕获所有常见异常。

  7. 与 Java 不同,C++ 中的所有异常都是未检查的,这意味着编译器不会确定异常是否被捕获(有关详细信息,请参阅此处)。因此,不需要在函数定义中列出所有未捕获的异常。尽管如此,这样做是一个好主意。

    
    #include <iostream>
    using namespace std;
    
    // Here we mainly specify the exceptions that this function will
    // throws.
    void fun(int *ptr, int x) throw (int *, int) // Dynamic Exception specification
    {
     if (ptr == NULL)
      throw ptr;
     if (x == 0)
      throw x;
     /* Some functionality */
    }
    
    int main()
    {
     try {
     fun(NULL, 0);
     }
     catch(...) {
      cout << "Caught the exception from fun()";
     }
     return 0;
    }
    
     
    

    输出

    
    Caught the exception from fun()
    
  8. 在 C++ 中,try/catch 块可以嵌套。此外,可以使用“throw;”重新抛出异常

    
    #include <iostream>
    using namespace std;
    
    int main()
    {
     try {
      try {
       throw 50;
      }
      catch (int n) {
       cout << "Handle Partially ";
       throw; // Re-throwing an exception
      }
     }
     catch (int n) {
      cout << "Handle remaining ";
     }
     return 0;
    }
    
     
    

    输出

    
    Handle Partially Handle remaining
    
  9. 抛出异常时,try 块内创建的所有对象在控制权传递给 catch 块之前都会被销毁。

    
    #include <iostream>
    using namespace std;
    
    class Test {
    public:
     Test() { cout << "Constructor of Test " << endl; }
     ~Test() { cout << "Destructor of Test " << endl; }
    };
    
    int main()
    {
     try {
      Test t1;
      throw 50;
     }
     catch (int i) {
      cout << "Caught " << i << endl;
     }
    }
    
     
    

    输出

    
    Constructor of Test 
    Destructor of Test 
    Caught 50