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 侯捷 孟岩  译

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值