C++

C++ 知识量:19 - 82 - 316

18.1 异常处理><

抛出异常- 18.1.1 -

在C++中,可以使用throw语句抛出异常。异常是程序在执行过程中出现的问题,它中断正常的执行流程,并且需要被及时处理。

下面是一个简单的例子,演示如何在C++中抛出异常:

#include <iostream>  
using namespace std;  
  
int main() {  
   int x;  
   try {  
      cout << "Enter an integer: ";  
      cin >> x;  
      if (x < 0) {  
         throw "Negative number entered";  
      }  
      cout << "You entered: " << x << endl;  
   } catch (const char* msg) {  
      cerr << "Exception caught: " << msg << endl;  
   }  
   return 0;  
}

在这个例子中,程序要求用户输入一个整数。如果输入的整数小于0,则会抛出一个异常,该异常是一个字符串类型的对象。程序使用try-catch块来捕获异常,其中try块包含可能会抛出异常的代码,而catch块则负责处理异常。在这个例子中,catch块输出一个错误消息,并返回一个非零值以指示程序出现了异常。

需要注意的是,在使用throw语句抛出异常时,应该在catch块中捕获并处理异常。如果没有适当的处理程序,程序将会中止执行并显示一个错误消息。

捕获异常- 18.1.2 -

在C++中,可以使用try-catch块来捕获异常。try块包含可能会抛出异常的代码,而catch块则负责处理异常。当try块中的代码抛出异常时,程序将跳转到匹配的catch块中处理异常。

下面是一个简单的例子,演示如何使用try-catch块捕获异常:

#include <iostream>  
using namespace std;  
  
int main() {  
   try {  
      throw "This is an exception";  
   } catch (const char* msg) {  
      cerr << "Caught an exception: " << msg << endl;  
   }  
   return 0;  
}

在这个例子中,try块中的代码抛出了一个字符串类型的异常。当这个异常被抛出时,程序跳转到匹配的catch块中处理异常。在这个例子中,catch块捕获了字符串类型的异常,并输出了一个错误消息。

需要注意的是,可以抛出和捕获任何类型的异常,包括内置类型、自定义类型和标准库类型。在catch块中,可以使用异常的类型来匹配要捕获的异常。如果抛出的异常与catch块中的类型不匹配,则程序将继续查找其他匹配的catch块,直到找到一个匹配的块或没有更多的块可以查找。如果没有找到匹配的catch块,则程序将中止执行并显示一个错误消息。

另外,还可以使用多个catch块来捕获不同类型的异常,每个块捕获一种特定类型的异常。这样可以使代码更加清晰和易于管理。下面是一个使用多个catch块的例子:

#include <iostream>  
using namespace std;  
  
int main() {  
   try {  
      throw 42; // 抛出一个整数类型的异常  
   } catch (int x) {  
      cerr << "Caught an integer exception: " << x << endl;  
   } catch (const char* msg) {  
      cerr << "Caught a string exception: " << msg << endl;  
   } catch (...) {  
      cerr << "Caught an unknown exception" << endl;  
   }  
   return 0;  
}

在这个例子中,程序抛出了一个整数类型的异常。第一个catch块捕获整数类型的异常,第二个catch块捕获字符串类型的异常,而第三个catch块捕获其他所有类型的异常。这样,无论程序抛出什么类型的异常,都可以被适当地处理。

noexcept异常说明- 18.1.3 -

在C++中,noexcept是一个关键字,用于指定函数是否抛出异常。如果一个函数被声明为noexcept,那么该函数保证不会抛出任何异常。如果该函数确实抛出了异常,那么程序将调用std::terminate函数,并且程序将立即终止。

在函数的声明中,可以将noexcept关键字放在函数声明的末尾,如下所示:

void foo() noexcept; // foo函数不会抛出任何异常

此外,如果noexcept关键字后面跟着一个括号,其中包含一个表达式,那么该表达式将在运行时计算,以确定是否应该抛出异常。如果该表达式抛出了异常,那么程序将调用std::terminate函数。

void foo() noexcept(false); // foo函数可能会抛出异常

在上面的示例中,noexcept(false)表示函数可能会抛出异常。如果函数确实抛出了异常,程序将调用std::terminate函数。

使用noexcept关键字可以告诉编译器该函数不会抛出异常,这有助于优化代码和提高程序的性能。如果一个函数被声明为noexcept,并且确实没有抛出任何异常,那么该函数的执行速度可能会比非noexcept函数更快。

异常类层次- 18.1.4 -

C++的异常层次结构主要包括以下几类:

  1. BaseException:这是所有C++异常的基类。它提供了用于异常处理的一些基本方法,比如what(),这个方法返回一个指向C风格字符串的指针,该字符串包含关于异常的描述。

  2. Exception:这是C++标准库异常的基类。这个类派生自BaseException类,并且提供了两个新的方法:throw_file()和throw_line()。这两个方法分别返回包含抛出异常的文件名和行号的字符串。

  3. LogicError和RuntimeError:这两个类是Exception的派生类。它们通常用于表示不同类型的异常。LogicError通常用于表示程序逻辑错误,比如无效的参数,而RuntimeError则用于表示其他类型的错误,比如内存耗尽。

  4. 具体的异常类型:这些是LogicError和RuntimeError的派生类,用于表示具体的错误情况。例如,invalid_argument是LogicError的派生类,用于表示无效的参数错误。