c++抛出异常 详解

  

1:
不可以抛出一个指向局部类的指针!因为,该局部类会在退出try的时候销毁!
不可以抛出一个指向局部类的引用. 原理同上.

2:
抛出一个局部的类对象时,thow先通过Copy构造函数构造一个新对象,再把该新对象传递给 catch.
因为局部对象在退出try时会被析构,所以,这里要构造一个新对象!!!

3:
在catch里面, 可直接用不带引用的变量, 可以用带引用的变量
eg: 如果
MyExcepctionStru e;
throw e; // 这里导致一次copy对象
那么可以
catch(MyExcepctionStru e) 或者 // 这里又导致一次copy对象, 共两次copy对象开销.
catch(MyExcepctionStru &e) // 这里没有, 只有throw时的一次copy对象开销.

如下示例代码, catch(A a)   将导致打印两次 "in copy construct"

  1. class A  
  2. {  
  3.     public:  
  4.     A()   
  5.     {     
  6.         printf("in construct/n");                                                                                                     
  7.         i = 10;   
  8.     }     
  9.     A(A& rhs)  
  10.     {     
  11.         printf("in copy construct/n");  
  12.         this->i = rhs.i;  
  13.     }     
  14.     int i;  
  15. };  
  16.   
  17. int main()  
  18. {  
  19.     try{  
  20.     A a;  
  21.     a.i = 30;   
  22.     throw a;  
  23.     }     
  24.     catch(A a)   
  25.     //catch(A a)   
  26.     {     
  27.         printf("catch exception/n");  
  28.         printf("a.i=%d ./n", a.i);  
  29.     }     
  30.     return 0;  
  31.   
  32. }  


当使用别人的库时, 别人的库抛异常, 如何处理?
这里以html_template类为例, 查看代码可以得知, 该类的process接口内部可能会抛两种异常, 这两种异常都是其基于stl::的标准异常类派生出来的异常类, 分别是syntax_ex和runtime_ex, 特别的, 两个异常类内部还包含了一些额外的辅助信息, 那么可以用如下代码处理该异
常,注意, what接口是stl的异常基类里面默认提供的.
库里面的定义的异常类代码:
  1. 101 //! template syntax exception class   
  2. 102 class syntax_ex : public std::runtime_error  
  3. 103 {  
  4. 104  public:  
  5. 105    //! path to template that caused the error   
  6. 106    std::string template_path;  
  7. 107   
  8. 108    //! problem line   
  9. 109    size_t line;  
  10. 110    //! error detail   
  11. 111    std::string detail;  
  12. 112   
  13. 113    //! ctructor   
  14. 114    syntax_ex(const std::string & str_what) :  
  15. 115    std::runtime_error(str_what)   
  16. 116    {  
  17. 117     detail = "";  
  18. 118     line   = 0;  
  19. 119    }  
  20. 120   
  21. 121    //! dtructor   
  22. 122    ~syntax_ex() throw() {}   
  23. 123 };  
  24.   
  25. 65   // 下面代码来自  std::runtime_error   
  26.      /** Returns a C-style character string describing the general cause of 
  27.  66      *  the current error (the same string passed to the ctor).  */  
  28.  67     virtual const char*  
  29.  68     what() const throw();      

  1. try  
  2. {  
  3.     strHtml = templ.Process();  
  4. }  
  5. catch (runtime_ex& e)  
  6. {  
  7.     error_log( "throw runtime_ex in Process(), msg: %s"  
  8.                "template_path: %s",   
  9.                e.what(),  
  10.                e.template_path.c_str()  
  11.                );  
  12.   
  13. }  
  14. catch (syntax_ex& e)  
  15. {  
  16.     error_log( "throw syntax_ex in Process(), msg: %s"  
  17.                "template_path: %s"  
  18.                "line : %d "  
  19.                "detail : %s ",  
  20.                e.what(),  
  21.                e.template_path.c_str(),  
  22.                e.line,  
  23.                e.detail.c_str()  
  24.                );  
  25. }  


如果
MyExcepctionStru *pe = new MyExcepctionStru();
throw pe;
那么可以
catch(MyExcepctionStru *pe)

{
   .... do something
   delete pe;
}

参考代码:

// 可以使任意的数据结构类型
struct MyExcepctionStru
{
    int dd;

}

main()

    try
    {
                 MyExcepctionStru myStru;
                 throw  &MyExcepctionStru ;   // !!! wrong !!!
                 

                 // Right
                 // 先通过MyExcepctionStru 的copy构造函数构造一个MyStru结构,再往下传递!!!
                 //  为什么不像通常的函数调用一样直接传递myStru呢???因为throw保证,
                  // C++保证:有异常抛出时,保证局部对象被析构!!!
                 throw MyExcepctionStru ;                       


                 // Right

                 MyStru* pMyStru = new MyStru();
                 throw pMyStru;        
    }
    catch( MyExcepctionStru*  pMyExcepctionStru)
    {
          delete pMyExcepctionStru;
    }
    catch(  pMyExcepctionStru& pMyExcepctionStru)
    {
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值