C++ 异常处理

辰星AI发布

C++ 通过 try/catch 语句来做异常处理,以下介绍常用的几种异常捕获和处理方式。

1. C 风格字符串异常

#include <iostream>
using namespace std;

double div_except_str(int a, int b) {
    if (b == 0) {
        throw "divider is zero";
    }

    return a / b;
}

int main() {
    try {
        div_except_str(1, 0);
    } catch (const char* except) {
        cout << except << endl;
    }

    return 0;
}

输出:

divider is zero

上述程序通过 throw 一个字符串异常,通过 try catch 语句块捕获,捕获的异常信息类型必须为 const char* 的 c 风格字符串。

2. 自定义普通异常类

自定义一个接受两个 int 型的 ExceptA 类,并通过 msg 函数输出异常信息:

#include <iostream>
using namespace std;

class ExceptA {
public:
    ExceptA(int v1, int v2) : a(v1), b(v2) {}

    void msg() { cout << "ExceptA " << a << ", " << b << endl; }

private:
    int a;
    int b;
};

double div_except(int a, int b) {
    if (b == 0) {
        throw ExceptA(a, b);
    }

    return a / b;
}

int main() {
    try {
        div_except(1, 0);
    } catch (ExceptA &except) {
        except.msg();
    }

    return 0;
}

输出:

ExceptA 1, 0

程序通过在检测到异常的地方 thow 一个 ExceptA 对象,try catch 捕获 ExeceptA 的引用,注意这里必须是引用类型。虽然 catch 的对象是 throw 对象的复制,这里依然使用引用的原因是可以支持同一个基类的多态。

3. 自定义异常类多态情形

一个申明抛出异常类型为基类的函数,可以抛出所有的子类异常,并被捕获。先定义异常类以及子类:

class ExceptBase {
public:
    ExceptBase(int v1, int v2) : a(v1), b(v2) {}

    virtual void msg() const { cout << "ExceptBase " << a << ", " << b << endl; }

protected:
    int a;
    int b;
};

class ExceptA : public ExceptBase {
public:
    ExceptA(int v1, int v2) : ExceptBase(v1, v2) {};

    virtual void msg() const { cout << "ExceptA " << a << ", " << b << endl; }
};

class ExceptASub : public ExceptA {
public:
    ExceptASub(int v1, int v2) : ExceptA(v1, v2) {};

    virtual void msg() const { cout << "ExceptASub " << a << ", " << b << endl; }
};

ExceptA 继承自 ExceptBase,ExceptASub 继承自 ExeceptA。msg 函数用于输出异常信息,定义为 virtual 虚函数允许子类重写。定义一个抛出基类类型异常的测试函数:

double test_except(int a, int b) throw (ExceptBase) {
    if (b == 0) {
        throw ExceptASub(a, b);
    }

    if (a == 0) {
        throw ExceptA(a, b);
    }

    throw ExceptBase(a, b);
}

函数在不同的参数情况下,抛出不同的异常类型。对应的 try catch 语句:

    try {
        test_except(1, 0);
        // test_except(0, 1);
        // test_except(1, 1);
    } catch (const ExceptASub &except) {
        except.msg();
    } catch (const ExceptA &except) {
        except.msg();
    } catch (const ExceptBase &except) {
        except.msg();
    }

必须从最外一层的子类开始匹配捕获。

C++ 默认的异常类

通过 exception 头文件包含基础的异常类型 exception,exception 提供 what 的虚方法返回 C 风格的字符串异常信息 const char *,子类可重写该方法。

class MyException : exception {
public:
    virtual const char *what() { return "MyException"; };
}

try {
    ...
} catch(const MyException & e) {
    cout << e.what() << endl;
    ...
}

c++ stdexcept 头文件中过定义了两个继承自 exception 的异常类:logic_error 和 runtime_error。两者均为 exception 的公有继承,并且提供一些更具体的子类类型异常。
logic_error:

  • domain_error: 定义域错误
  • invalid_argument:无效参数
  • length_error:长度错误

runtime_error:

  • range_error
  • overflow_error
  • underflow_error
分类: c++语言

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注