TICPP-VOL2-读书笔记-异常处理

生存理由:
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

Leave a Reply