第十三章、异常

异常(Exception)是 C++ 提供的一种处理程序运行时错误的机制,它运行程序时检测错误,并快速返回到上层调用的地方进行错误处理,同时会调用栈上创建对象的析构函数。

C++ 程序在执行时通常用两个流程:正常流程异常流程

正常流程的程序在函数调用是通常使用 return 语句一层一层的向上返回到函数调用者。而异常流程则可以进入异常状态,在异常状态下略过程序的正常执行的代码快速返回到上层,直至找到能够处理此异常状态的 try 语句,程序才重新回到正常状态。

正常状态的程序执行流程

fa() ---> fb() ---> fc() ---> fd()
   ^       | ^      |  ^       |
   |       | |      |  |       |
   +-------+ +------+  +-------+

异常状态的程序执行流程

fa() ---> fb() ---> fc() ---> fd()
   ^                           |
   |                           |
   +----------------——---------+

异常相关的关键字

try    catch    throw

1. throw 语句

throw 语句用于抛出错误,让程序进入异常状态(走异常路径),返回到上层调用处等待处理。

语法

throw 错误对象;

说明

示例

// filename: throw.cpp
#include <iostream>

using namespace std;

class MyRange{
    public:
        MyRange(int begin, int end, int stp=1): start(begin), stop(end), step(stp) {}
        // 重载 [] 运算符
        int operator [] (int index) {
            int value = start + index * step;
            if (index < 0)
                throw "索引不能为负数值";
            if (step > 0 && value > stop)
                throw "索引越界";
            else if (step < 0 && value < stop)
                throw "索引越界";

            return value;
        }
    private:
        int start;
        int stop;
        int step;
};

int main(int argc, char * argv[]) {
    MyRange r2(1, 10, 3);  // 生成 1、4、7

    cout << r2[0] << endl;  // 打印 1
    cout << r2[1] << endl;  // 打印 4
    cout << r2[-1] << endl;  // 抛处 const char * 类型的错误
    cout << r2[100] << endl;  // 抛处 const char * 类型的错误

    printf("程序正常退出!\n");
    return 0;
}

编译和运行结果如下:

weimz@mzstudio:~$ g++ -o throw throw.cpp
weimz@mzstudio:~$ ./throw 
1
4
terminate called after throwing an instance of 'char const*'
已中止                  (核心已转储) ./throw
weimz@mzstudio:~$ 

从上述运行结果可知,当执行表达式 r2[-1] 时,调用成员函数 operator[],此处使用 throw "索引不能为负数值"; 语句抛出 const char * 类型的错误并进入异常状态(进入异常返回流程),由于上层调用者没有使用 try 语句接收此异常。此异常一直穿透 main 函数。最终程序被异常终止。如果需要让程序接收此错误信息并转为正常状态,则需要使用 try 语句进行接收并处理错误。