读书笔记--异常处理(3)

来源:互联网 发布:周子瑜日本人气 知乎 编辑:程序博客网 时间:2024/05/21 16:50

    exception类所以定义的唯一操作是一个what的虚成员,返回const char 的对象,一般返回用来在抛出位置构造异常对象的信息
                                                       |---overflow_error
                      |--runtime_error---|---underflow_error
                      |                                |---range_error
                      |                   
                      |---bad_cast

exception----|   
                       |---bad_alloc
                       |                          |---domain_error     
                       |                          |---invalid-argument 
                       |---logic_error--|---out_of_range
                                                  |---length-error
   
//throw exception if both objects do not refer to the same
Sales_item operator+(const Sales_item &lhs,const Sales_item &rhs)
{
 if( !rhs.same_isbn(rhs) )
 {
  throw isbn_mismatch("ISBN mismatch",lhs.book(),rhs.book());
 }
 Sales_item ret(lhs);
 
 //copy lhs into a local object,that we'll return
 ret += rhs;
 
 return ret;   //return ret by value
}

//use hypothctical bookstore exception
Sales_item item1,item2,sun;
while( cin >> item1 >> item2 )  //read two transactions
{
 try
 {
  sum = item1 + item2;    //calculate their sum
 }
 catch( const isbn_mismatch &e )
 {
  cerr << e.what() << ":left isbn(" << e.left << ")right isbn(" << e.right << ")" << endl;
 }
}

    自动资源释放的问题,来考虑如下函数

void f()
{
 vector<string> v;   //local vector
 string s;
 while( cin >> s )
 {
  v.push_back(s);    //populate the vector
 }
 string *p=new string[v.size()];   //dynameic array
 delete []p;
}//v destroyed antomatically when the function

    这个函数定义了一个局部vector并动态分配了一个数组,在正常情况下,数组合vector都在退出函数前被撤销,函数中最后一个语句释放数组,在函数结束时自动撤销vector
   但是,如果在函数内部发生异常,则撤销vector而不释放数组,在new之后但在delete之前发生的异常时的数组没被撤销。这时,可通过定义一个泪来封装资源的分配和释放,这一技术称为“分配既初始化” ,简称RAII。
  
class Resource
{
 public:
  Resource(parms p):r(allocate(p)){}
  ~Resource(){release(r);}
  //also heed to define copy and assigment
 private:
  resource_type *r;//resouce managed by this type
  resource_type *allocate(parms p);//allocate
  void release(resource_type *);//free this resource
};

 Resource类分配资源和回收资源的类型,它保存表示资源的数据成员
 
void fcn()
{
 Recouse res(args);//allocates resourse_type
 //code that might throw an exception
 //if exception occurs,destructor for res is run
 //automatically
 //...
}

 资源分配技术中的auto_ptr类:
 auto_ptr类在头文件memory中
 auto_ptr<T> ap; 创建为ap的为绑定的auto_ptr对象
 auto_ptr<T> ap1(p); 创建名为ap1的auto_ptr对象,ap1拥有指针p指向的对象,构造函数为explicit
 auto_ptr<T> ap1(ap2); 创建名为ap1的auto_ptr对象,ap1保存原来存储在ap2中的指针,将所有权转移给ap1,ap2成为未绑定的                          auto_ptr对象
 ap1=ap2; 向所有权从ap2转给ap1,删除ap1的对象并且使ap1指向ap2指向的对象,使ap2未绑定
 ap.reset(p); 如果p与ap值不同,则删除ap指向的对象,并且将ap邦到p
 ap.release(); 返回ap所保存的指针并且使ap成为未绑定
 ap.get(); 返回ap保存的指针
 
 auto_ptr不能用于管理从new返回的一个对象,不能管理动态分配数组,当auto_ptr被复制或赋值德时候,会出错,且不能将其存储在标准库容其中
void f()
{
 int *p=new int(42);  //dynamically allocate a new obj
 delete p;
}

 如果在上述代码的new和delete之间发生异常,且不被局部捕获,则永远不会受内存,则用auto_ptr可以改善
void f()
{
 auto_ptr<int> ap(new int(42)); //allocate new obj
 //...
}  //auto_ptr freed automatically when funcation ends

 auto_ptr类可以接受任何类型指针的模板
 auto_ptr<string> ap(new string("Banana"));
 任意auto_ptr对象初始化是由new表达式返回的对象的地址接受构造函数explicit。所以必须使用初始化的直接形式来创建auto_ptr对象
autp_ptr<int> pi=new int(1024); //error
auto_ptr<int> pi=(new int(1024)); //ok

auto_ptr<string> ap1(new string("stegos"));
auto_ptr<string> ap2(ap1);
 当复制auto_ptr对象或者对auto_ptr对象赋值时,右边的auto_ptr对象让出对基础对象的所有职责,并重置为未绑定的auto_ptr,若不置为空对象,则当删除所有指向内存时,就会重复删除
 
 如要测试auto_ptr对象是否有效,可以通过get成员函数,返回包含auto_ptr对象中的基础指针
//revised test to guarantee p_auto reders to an obj
if( auto_ptr.get() )
{
 //...
}
 auto_ptr对象与内置指针的另外一个区别是,不能直接将一个地址赋给auto_ptr对象,相反,必须调用reset函数
if( !auto_ptr.get() )
{
 auto_ptr.reset(new int(1024));
}