生存理由:
1.异常处理远离异常发生地
2.针对对象的释放资源的管理
try
{
// ur code
throw ;//exception style
}
catch(type n)
{
//handle exceptions of type
}
异常处理模型:中止&恢复模型.
一.异常匹配
原则1.对象或者指向派生类对象的引用都会与其基类处理器匹配.
原则2.捕获所有异常
catch(…)
{
}
原则3.重新抛出异常,应用于调用链高层次异常处理.呵呵,就是高层处理底层异常.
catch(…)
{
//ur code
throw;
}
原则4.不捕获异常.不是真正不捕获,是从底层到高层,寻找合适的异常处理器.如果没有,那么执
行,terminate()函数,其调用了abort()函数.
后果:全局对象&静态对象析构函数没有执行
set_terminate()函数制作自己的中止函数.
析构函数抛出异常几乎被禁止.
二.清理.就是资源释放.
原则5.
难点在于构造函数异常处理,处理方式:构造函数发生异常,析构函数不被调用.
第一种
1.构造函数捕获异常,用于资源释放
2.对象构造函数分配资源,析构函数释放资源.
原子性的处理.
第二种,用模板封装指针的方法.
template<class T,int sz =1> class PWrap{
T * Ptr;
public:
class RangeError();
PWrap(){
Ptr = new T[sz];
}
~Pwrap(){
delete []Ptr;
}
T& operator[](int i) throw(RangeError)
{
if(i>=0 && i<sz) return Ptr[i];
throw RangeError();
}
}
原则6.使用auto_ptr对象.
class A{
public:
void test(){cout<<"test"<<endl}:
}
int main()
{
auto_ptr<A> pObject(new A());
pObject->test(); //test is an object of auto_ptr
}
三.标准异常.
使用c++的标准异常可以大大提高工作效率.
四.异常规格说明.
example: void f() throw(toobig,toosmall,divzero) //函数捕获throw的三种异常
void g() //捕获任何可能异常
void h() throw() //不捕获任何异常
原则7.unexpected()&set_unexpected()的使用
example:
#include <exception>
#include <iostream>
using namespace std;
class up();
class fit();
void g();
void f(int i) throw(up,fit){
switch(i)
{
case 1: throw up();
case 2: throw fid();
}
g();
}
void g(){}; // version 1
void g(){throw 47} //version 2
void my_unexpected(){
exit(0);
}
int main(){
set_unexpected(my_unexpectd);
for(int i=1;i<=3;i++)
try{
f(i);
}
catch(up){
cout<<"up caught"<<endl;
}
catch(fit)
{
cout<<"fit caught"<<endl;
}
}
原则8.unexpected()抛出的异常类型不违反触发unexpected()的函数的异常规格说明的话,
函数恢复到函数被调用位置重新开始.
#include <exception> // For std::bad_exception
#include <iostream>
#include <cstdio>
using namespace std;
// Exception classes:
class A {};
class B {};
// terminate() handler
void my_thandler() {
cout << "terminate called" << endl;
exit(0);
}
// unexpected() handlers
void my_uhandler1() { throw A(); }
void my_uhandler2() { throw; }
// If we embed this throw statement in f or g,
// the compiler detects the violation and reports
// an error, so we put it in its own function.
void t() { throw B(); }
void f() throw(A) { t(); }
void g() throw(A, bad_exception) { t(); }
int main() {
set_terminate(my_thandler);
set_unexpected(my_uhandler1);
try {
f();
} catch(A&) {
cout << "caught an A from f" << endl;
}
set_unexpected(my_uhandler2);
try {
g();
} catch(bad_exception&) {
cout << "caught a bad_exception from g" << endl;
}
try {
f();
} catch(…) {
cout << "This will never print" << endl;
}
} ///:~
原则9.如果函数规格说明包括bad_exception,则unexpected()函数抛出异常替换为bad_expection.
原则10.如果函数规格说明不包括bad_exception,则调用terminated()函数.
原则11.派生类跟基类要遵循is-a的关系.
#include <exception> // For std::bad_exception
#include <iostream>
#include <cstdio>
using namespace std;
// Exception classes:
class A {};
class B {};
// terminate() handler
void my_thandler() {
cout << "terminate called" << endl;
exit(0);
}
// unexpected() handlers
void my_uhandler1() { throw A(); }
void my_uhandler2() { throw; }
// If we embed this throw statement in f or g,
// the compiler detects the violation and reports
// an error, so we put it in its own function.
void t() { throw B(); }
void f() throw(A) { t(); }
void g() throw(A, bad_exception) { t(); }
int main() {
set_terminate(my_thandler);
set_unexpected(my_uhandler1);
try {
f();
} catch(A&) {
cout << "caught an A from f" << endl;
}
set_unexpected(my_uhandler2);
try {
g();
} catch(bad_exception&) {
cout << "caught a bad_exception from g" << endl;
}
try {
f();
} catch(…) {
cout << "This will never print" << endl;
}
} ///:~
原则12.异常规格说明主要为非模板类实现.
五.异常安全.
原则13.使用clone技术实现新增对象的安全分配内存&初始化.
六.异常使用原则.
原则14.避免使用异常
1.异步事件.2.处理简单错误.3.程序流程控制.4.强迫使用5.新异常,老代码.
原则15.使用异常.
1.使用异常规格说明时,要编写自己的unexpected函数.
2.尽量使用标注异常.
3.嵌套用户自己的异常.
4.使用异常层次结构.捕获基类型异常.
5.多重继承.
6.引用捕获异常.
7.构造函数中抛出异常.
8.不在析构函数抛出异常.
9.避免悬挂指针.auto_ptr