赞
踩
malloc()
;例外shmat()
失败返回值为MAP_INVALD(-1)
fread()
/fwrite()
返回读写字符长度size_t
,超出长度表示失败。errno
异常提供一个错误专用通道。
优点:
异常分为两个部分:
throw 表达式;
try {
// 保护代码 包含可能抛出异常的语句;
} catch (类型名 [形参名]) {
// catch块 处理异常
}
特点
异常机制
try-throw-catch
的目标是问题检测与问题解决分离
复杂一点地写法
try {
// 保护代码 包含可能抛出异常的语句;
} catch (类型名1 [形参名]) {
// catch块 处理异常
} catch (类型名2 [形参名]) {
// catch块 处理异常
} catch (类型名3 [形参名]) {
// catch块 处理异常
} catch(...){
// catch块 处理异常
}
注意
catch
都能接受相同异常,只有最前面的一个可以接收到。catch(...)
只能放在所有异常捕获的最后返回值类型 函数() throw(异常列表);
throw(异常列表)
默认可以抛出所有异常。throw()
。异常处理机制保证:
try
到throw
语句之间构造起来的对象的析构函数将被自动调用。main
函数后还没有找到匹配的catch
块,那么系统调用terminate()
终止整个程序,这种情况下不能保证所有局部对象会被正确地销毁。举例
#include <iostream>
using namespace std;
void test(){
cout << "before throw." << endl;
throw -1;
cout << "after throw." << endl;
}
int main(){
try{
test();
}catch(int a){
cout << "exception:" << a << endl;
}
}
#include <iostream> using namespace std; class Test{ public: Test(){ cout << "Test Init" <<endl; } ~Test(){ cout << "Test Destroy" <<endl; } }; int main(){ try{ Test t; cout << "before throw." << endl; throw -1; cout << "after throw." << endl; }catch(int a){ cout << "exception:" << a << endl; } }
注意事项
- 如果抛出的异常一直没有函数捕获(
catch
),则会一直上传到c++运行系统那里,导致整个程序的终止。- 一般在异常抛出后资源可以正常被释放,但注意如果在类的构造函数中抛出异常,系统是不会调用它的析构函数的。
处理方法是:如果在构造函数中要抛出异常,则在抛出前要记得删除申请的资源。- 异常处理仅仅通过类型而不是通过值来(switch-case)匹配的,所以
catch
块的参数可以没有参数名称,只需要参数类型。- 函数原型中的异常说明要与实现中的异常说明一致,否则容易引起异常冲突。
- 应该在
throw
语句后写上异常对象时,throw
先通过Copy构造函数
构造一个新对象,再把该新对象传递给catch
.catch
块的参数推荐采用地址传递而不是值传递,不仅可以提高效率,还可以利用对象的多态性。另外,派生类的异常扑获要放到父类异常扑获的前面,否则,派生类的异常无法被扑获。- 编写异常说明时,要确保派生类成员函数的异常说明和基类成员函数的异常说明一致,即派生类改写的虚函数的异常说明至少要和对应的基类虚函数的异常说明相同,甚至更加严格,更特殊。
exception
派生异常类 | 作用 |
---|---|
logic_error | 逻辑错误,在程序运行前可以检测出来 |
runtime_error | 运行时错误,仅在程序运行中检测到 |
logic_error
派生异常类 | 作用 |
---|---|
domain_error | 违反了前置条件 |
invalid_argument | 指出函数的一个无效参数 |
length_error | 指出有一个超过类型size_t的最大可表现值长度的对象的企图 |
out_of_range | 参数越界 |
bad_cast | 在运行时类型识别中有一个无效的dynamic_cast 表达式 |
bad_typeid | 报告在表达试typeid (*p)中有一个空指针p |
runtime_error
派生异常类 | 作用 |
---|---|
range_error | 违反后置条件 |
bad_alloc | 存储分配错误 |
尝试捕获逻辑异常和运行时异常
class 异常类:public exception {
public:
const char* what()const throw() {
return 信息字符串;
}
};
为什么很多经典书籍鼓励使用异常,但是实际开发中很多C++编码规范却禁用异常?
C++异常机制在语法上是更加优雅的处理错误,但是实际上编译出来的程序会有一些性能损失,另外错误地使用异常处理代码会变得更加复杂。
编译器选项
g++
特殊编译选项g++ -fno-exceptions
在不同的编码规范中,对是否使用异常存在争议。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。