C++异常机制概述

作者:melonstreet 整理:cpp开发者 出处:https://www.cnblogs.com/QG-whz/
以下是正文
C++异常机制概述
一个最简单的 try...catch... 的例子如下所示。我们有个程序用来记班级学生考试成绩,考试成绩分数的范围在 0-100 之间,不在此范围内视为数据异常:
int main(){int score=0;while (cin >> score){try{if (score > 100 || score < 0){throw score;}//将分数写入文件或进行其他操作}catch (int score){cerr << "你输入的分数数值有问题,请重新输入!";continue;}}}
throw 表达式;//示例代码:throw包含在外层函数的try块中void registerScore(int score){if (score > 100 || score < 0)throw score; //throw语句被包含在外层main的try语句块中//将分数写入文件或进行其他操作}int main(){int score=0;while (cin >> score){try{registerScore(score);}catch (int score){cerr << "你输入的分数数值有问题,请重新输入!";continue;}}}

异常对象
| 标准异常类 | 描述 | 头文件 |
|---|---|---|
| exception | 最通用的异常类,只报告异常的发生而不提供任何额外的信息 | exception |
| runtime_error | 只有在运行时才能检测出的错误 | stdexcept |
| rang_error | 运行时错误:产生了超出有意义值域范围的结果 | stdexcept |
| overflow_error | 运行时错误:计算上溢 | stdexcept |
| underflow_error | 运行时错误:计算下溢 | stdexcept |
| logic_error | 程序逻辑错误 | stdexcept |
| domain_error | 逻辑错误:参数对应的结果值不存在 | stdexcept |
| invalid_argument | 逻辑错误:无效参数 | stdexcept |
| length_error | 逻辑错误:试图创建一个超出该类型最大长度的对象 | stdexcept |
| out_of_range | 逻辑错误:使用一个超出有效范围的值 | stdexcept |
| bad_alloc | 内存动态分配错误 | new |
| bad_cast | dynamic_cast类型转换出错 | type_info |
catch 关键字
允许从非常量到常量的类型转换。
允许派生类到基类的类型转换。
数组被转换成指向数组(元素)类型的指针。
函数被转换成指向函数类型的指针。
catch(type x){//做了一部分处理throw;}
栈展开、RAII
//一个没有任何意义的类class A{public:A() :a(0){ cout << "A默认构造函数" << endl; }A(const A& rsh){ cout << "A复制构造函数" << endl; }~A(){ cout << "A析构函数" << endl; }private:int a;};int main(){try{A a ;throw a;}catch (A a){;}return 0;}
程序将输出:

int main(){try{A * a= new A;throw *a;}catch (A a){;}getchar();return 0;}
程序运行结果:

RAII机制有助于解决这个问题,RAII(Resource acquisition is initialization,资源获取即初始化)。它的思想是以对象管理资源。为了更为方便、鲁棒地释放已获取的资源,避免资源死锁,一个办法是把资源数据用对象封装起来。程序发生异常,执行栈展开时,封装了资源的对象会被自动调用其析构函数以释放资源。C++ 中的智能指针便符合RAII。关于这个问题详细可以看《Effective C++》条款13.
C++ 类构造函数初始化列表的异常机制,称为 function-try block。一般形式为:
myClass::myClass(type1 pa1)try: _myClass_val (初始化值){/*构造函数的函数体 */}catch ( exception& err ){/* 构造函数的异常处理部分 */};
若析构函数抛出异常,调用 std::abort() 来终止程序。
在析构函数中 catch 捕获异常并作处理。
noexcept修饰符与noexcept操作符
void func() throw(int ,double ) {...}void func() throw(){...}
这是 throw 作为函数异常说明,前者表示 func()这个函数可能会抛出 int 或 double 类型的异常,后者表示 func() 函数不会抛出异常。事实上前者很少被使用,在 C++11 这种做法已经被摒弃,而后者则被 C++11 的 noexcept 异常声明所代替:
void func() noexcept {...}//等价于void func() throw(){...}
void func() noexcept(常量表达式);关于C++异常机制,欢迎在评论中和我探讨。觉得文章不错,请点赞和在看支持我继续分享好文。谢谢!
评论
