STL-----錯誤(error)處理和異常(exception)處理

C++標準程序庫由不同的成分構成。來源不同,設計與實現風格迥異。而錯誤處理和異常處理正是這種差異的一個典型體現。

1.1 標準異常類別

 

  語言本身或者標準庫所拋出的所有異常,都派生自積累exception.這是其它數個標準異常類別的基類,它們共同構成一個類體系具體如下:

這些標準異常可分爲三組:{1.語言本身支持的異常;2.C++標準程序庫發出的異常;3.程序作用域(scope of a program)之外發出的異常}

exception:

 1)bad_alloc

 2)bad_cast

 3)bad_typied

 4)logic_error {domain_error、invalid_argument、length_error、out_of_range}

 5)ios_base::failure

 6)runtime_error {range_error、overflow_error、underflow_error}

 7)bad_exception

1.1.1 語言本身支持的異常

   此類異常用以支撐某些語言特性,所以從某種角度來說它們不是標準程序庫的一部分,而是核心語言的一部分。如果以下操作失敗,就會拋出這類異常。

  ----全局操作符new操作失敗,就會拋出bad_alloc異常(若採用new的nothrow版本,就另當別論)。由於這個異常可能於任何時間在任何複雜的程序中發生,所以可說是最重要的一個異常。

  ----執行期間,當一個加諸於reference身上的"動態性別轉換操作"失敗時,danamac_cast會拋出bad_cast異常。

  ----執行期型別辨識(RTTI)過程中,如果交給typeid的參數爲零或空指針,typeid操作符會拋出bad_typeid異常。

  ----如果發生非預期的異常,bad_exception異常會接手處理,方式如下:當函數拋出異常規格(excepiton specification)以外的異常,bad_excepiton就會調用unexcepted()。例如:

 class E1;
 class E2;//not derived from E1
 void f() throw(E1)//throws only excepiton of type E1
 {
    ...
    throw E1();//throws eception of type E1
    ...
    throw E2();//calls unexcepted(),which calls
    terminate()
 }

f()之中拋出“型別爲E2”的異常,這種動作違反了異常規則(exception specification)的設定,於是喚起了unexcepted(),後者通常喚起了terminate()終止程序。

  然而如果在你的異常規則中列出bad_exception,那麼unexcepted()縱使會重新拋出(rethrow)bad_exception異常。

  class E1;

  class E2;//not derived from E1

   void f() throw(E1,std::bad_exception)//throws only excepiton of type E1 or

                            //bad_exception for any other exception type
 {
    ...
    throw E1();//throws eception of type E1
    ...
    throw E2();//calls unexcepted(),which calls
    bad_exception
 }

 

 

1.1.2 C++標準程序庫所發生的異常

  C++標準程序庫異常縱使派生自logic_error。從理論上講,我們能夠通過一些手段,從程序中避免邏輯錯誤。所謂邏輯錯誤包括違背邏輯前提或者違反class的不變性。C++ STL提供以下邏輯錯誤類別:

1)invalid_argument表示無效參數,例如講bitset(array of bits)以char而非'0'或'1'進行初始化。

2)length_error指出某個行爲"可能超越了最大極限",例如對着某個字符串附加太多字符。

3)out_range 指出參數值“不在預期範圍之內”,例如在諸如array的容器或字符串(string)中採用一個錯誤索引。

4)domain_error指出專業領域範疇內的錯誤。

 

  此外,標準程序庫的I/O部分提供了一個ios_base::failure的特殊異常。當數據流(data stream)由錯誤或由到達文件尾端而發生狀態改變時,就可能跑出這個異常。

1.1.3 程序作用域(scope of a program)之外發生的異常

派生自runtime_error的異常,用來指出“不在程序範圍內,且不容易迴避“的事件。C++標準程序庫對執行期錯誤提供了一下三個classes:

1)range_error指出內部算術運算髮生區間錯誤(range error)

2)overflow_error指出算術運算髮生上溢位(overflow)

3)underflow_error指出算術運算髮生下溢位(underflow)

【注】基礎類別exception 和bad_exception定義於<exception>。bad_alloc定義於<new>

 bad_cast 和bad_typeid定義於 <typeinfo>,ios_base::failure定義於 <ios>,其它異常類別定義於<stdexcept>。

 

1.2異常類別(exception class)的成員

  爲了catch字句中處理異常,必須採用異常所提供的藉口。所有標準異常的接口只含一個成員函數:what(),用以獲取"型別本身以外的附件信息"。它返回一個以null結束的字符串:

namespace std{

  class exception{

    public:

    virtual const char  *what() const throw();

    ...

  };

}

 

what()返回的c-string在其所屬的異常對象被摧毀後,就不再有效了。

標準異常的其它成員,用來處理生成、複製、銷燬等動作。要注意的是,除了what()外,再沒有任何異常提供任何其它成員函數,能夠描述異常的種類。例如:沒有可找出異常上下文(context)的一致性方法,或找出區間錯誤(range error)發生時的錯誤索引值。因此,唯一通過用的異常評估手段,大概只有打印一途了:

try{

  ...

}

catch(const std::exception& error){

  //print implementation-defined error message

  std::cerr<<error.what()<<std::endl;

  ...

}

 

 

1.3拋出標準異常

  你可以在自己的程序庫或程序內部拋出某些標準異常。允許你這般運用的各個標準異常,生成時都只需要一個string參數,它將被waht()返回的描述字符串。例如logic_error定義如下:

namespace std{

  class logic_error :public exception{

    public:

    explicit logic_error(const string& whatString);

  };

}

提供這種功能的標準異常有:logic_error及其派生類別、runtime_error及其派生類別、ios_base::failure.你不能拋出exception,也不能拋出任何用以支持語言核心性質的異常。

  想要拋出一個標準異常,只需生成一個描述符異常的字符串,並將它初始化,交給異常對象;

std::string s;

...

throw std::out_of_range(s);

 

由char*可被隱式轉換爲string,所以你可以直接使用字符串字面量;

throw std::out_of_range("out_of_range(somewhere,somehow)");

 

1.4從標準異常類別(exception class)中派生新類別

  另一個在程序中採用標準異常類別的可能情況是,定義一個直接或間接派生自exception的特定異常類別。要這麼做,首先必須確保what()機制正常運作,what()是個虛擬函數,所以提供what()方法之一就是自己實現what();

namespace std MyLib{
  /*user-defined exception class,

  *derived from a standard class for exceptions

  */

  class MyProblem : public std::exception{

    public:

    ...

    MyProblem(...);{//special constructor

    }

    virtual const char * what() const  throw(){//what() function

    ...

    }

  };

  ...

   void f(){

    ...

    //create an exception object and throw it

   throw MyProblem(...);

   }

}

 

 

 

 

 

 

 

 

參考:The C++ Standard Library 侯捷 孟巖  譯

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章