Home C&C++函数库 c++ 语法 程序源码 Linux C库

异常处理


异常处理提供了一种对程序中的异常情况(如运行时错误)作出反应的方法, 该方法是将异常转移到称为异常处理程序的特殊函数。

为了捕获异常,将代码的一部分置于异常检查之下。这可以通过将这部分代码封装在try-block中来实现。 当该块中出现异常情况时,抛出一个异常,将控制权转移到异常处理程序。 如果没有抛出异常,代码将正常继续,并忽略所有处理程序。

在try语句块中使用throw关键字抛出异常。异常处理程序是用关键字catch来声明的,它必须放在try块的后面:

// exceptions
#include <iostream>
using namespace std;

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

异常处理下的代码封装在一个try块中。在这个例子中,这段代码只是抛出一个异常:

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++弃用,但仍受支持。 动态异常说明紧跟在函数声明之后,并附加抛出说明符。例如:

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,定义在<exception>头文件中。该类有一个名为what的虚成员函数, 该函数返回一个以空结束的字符序列(类型为char *), 可以在派生类中重写该函数以包含对异常的某种描述。

// using standard exceptions
#include <iostream>
#include <exception>
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;
}
My exception happened.

我们放置了一个通过引用捕获异常对象的处理程序(注意类型后面的&号), 因此它也捕获来自exception的类,比如myexception类型的myex对象。

所有由c++标准库的组件抛出的异常都来自于这个异常类。这些都是:

异常 描述
bad_alloc 由new抛出的分配失败
bad_cast 当动态类型转换失败时由dynamic_cast抛出
bad_exception 由某些动态异常说明符引发
bad_typeid typeid抛出
bad_function_call 由空函数对象抛出
bad_weak_ptr 当传递一个错误的weak_ptr时由shared_ptr抛出

同样从exception派生的头文件<exception>定义了两种泛型异常类型,可以被自定义异常继承来报告错误:

异常 描述
logic_error 与程序内部逻辑有关的错误
runtime_error 运行时检测到错误

需要检查标准异常的典型例子是内存分配:

// bad_alloc standard exception
#include <iostream>
#include <exception>
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派生于标准基类异常,所以可以捕获它(通过引用捕获,捕获所有相关的类)。


联系我们 免责声明 关于CandCplus 网站地图
>