📜  C++异常处理

📅  最后修改于: 2020-12-17 05:14:17             🧑  作者: Mango


例外是在程序执行期间出现的问题。 C++异常是对程序运行时出现的异常情况的一种响应,例如试图除以零。

异常提供了一种将控制权从程序的一部分转移到另一部分的方法。 C++异常处理基于三个关键字构建: try,catchthrow

  • throw-问题出现时,程序将引发异常。这是使用throw关键字完成的。

  • catch-程序在要处理问题的程序中的某个位置使用异常处理程序捕获异常。 catch关键字指示捕获异常。

  • trytry块标识将为其激活特定异常的代码块。随后是一个或多个捕获块。

假设一个块将引发异常,则一种方法使用trycatch关键字的组合来捕获异常。在可能产生异常的代码周围放置了一个try / catch块。 try / catch块中的代码称为受保护的代码,使用try / catch的语法如下-

try {
   // protected code
} catch( ExceptionName e1 ) {
   // catch block
} catch( ExceptionName e2 ) {
   // catch block
} catch( ExceptionName eN ) {
   // catch block
}

您可以列出多个catch语句以捕获不同类型的异常,以防在不同情况下try块引发多个异常。

抛出异常

可以使用throw语句在代码块内的任何位置抛出异常。 throw语句的操作数确定异常的类型,可以是任何表达式,表达式结果的类型确定抛出的异常的类型。

以下是发生除以零的条件时引发异常的示例-

double division(int a, int b) {
   if( b == 0 ) {
      throw "Division by zero condition!";
   }
   return (a/b);
}

捕捉异常

try块之后的catch块捕获任何异常。您可以指定要捕获的异常类型,这取决于关键字catch后面括号中的异常声明。

try {
   // protected code
} catch( ExceptionName e ) {
  // code to handle ExceptionName exception
}

上面的代码将捕获ExceptionName类型的异常。如果要指定catch块应处理在try块中引发的任何类型的异常,则必须在包含异常声明的括号之间放置省略号…,如下所示-

try {
   // protected code
} catch(...) {
  // code to handle any exception
}

以下是一个示例,该示例引发了一个被零除的异常,我们将其捕获在catch块中。

#include 
using namespace std;

double division(int a, int b) {
   if( b == 0 ) {
      throw "Division by zero condition!";
   }
   return (a/b);
}

int main () {
   int x = 50;
   int y = 0;
   double z = 0;
 
   try {
      z = division(x, y);
      cout << z << endl;
   } catch (const char* msg) {
     cerr << msg << endl;
   }

   return 0;
}

因为我们引发了const char *类型的异常,所以在捕获此异常时,我们必须在catch块中使用const char *。如果我们编译并运行以上代码,这将产生以下结果-

Division by zero condition!

C++标准异常

C++提供了在定义的标准异常列表,我们可以在程序中使用它们。这些按以下所示的父子类层次结构排列-

C++异常层次结构

这是上述层次结构中提到的每个异常的简短描述-

Sr.No Exception & Description
1

std::exception

An exception and parent class of all the standard C++ exceptions.

2

std::bad_alloc

This can be thrown by new.

3

std::bad_cast

This can be thrown by dynamic_cast.

4

std::bad_exception

This is useful device to handle unexpected exceptions in a C++ program.

5

std::bad_typeid

This can be thrown by typeid.

6

std::logic_error

An exception that theoretically can be detected by reading the code.

7

std::domain_error

This is an exception thrown when a mathematically invalid domain is used.

8

std::invalid_argument

This is thrown due to invalid arguments.

9

std::length_error

This is thrown when a too big std::string is created.

10

std::out_of_range

This can be thrown by the ‘at’ method, for example a std::vector and std::bitset<>::operator[]().

11

std::runtime_error

An exception that theoretically cannot be detected by reading the code.

12

std::overflow_error

This is thrown if a mathematical overflow occurs.

13

std::range_error

This is occurred when you try to store a value which is out of range.

14

std::underflow_error

This is thrown if a mathematical underflow occurs.

定义新异常

您可以通过继承和覆盖异常类功能来定义自己的异常。以下是示例,显示了如何使用std :: exception类以标准方式实现自己的异常-

#include 
#include 
using namespace std;

struct MyException : public exception {
   const char * what () const throw () {
      return "C++ Exception";
   }
};
 
int main() {
   try {
      throw MyException();
   } catch(MyException& e) {
      std::cout << "MyException caught" << std::endl;
      std::cout << e.what() << std::endl;
   } catch(std::exception& e) {
      //Other errors
   }
}

这将产生以下结果-

MyException caught
C++ Exception

在此, what()是异常类提供的公共方法,并且已被所有子异常类覆盖。这将返回异常原因。