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"
- class A
- {
- public:
- A()
- {
- printf("in construct/n");
- i = 10;
- }
- A(A& rhs)
- {
- printf("in copy construct/n");
- this->i = rhs.i;
- }
- int i;
- };
- int main()
- {
- try{
- A a;
- a.i = 30;
- throw a;
- }
- catch(A a)
- //catch(A a)
- {
- printf("catch exception/n");
- printf("a.i=%d ./n", a.i);
- }
- return 0;
- }
当使用别人的库时, 别人的库抛异常, 如何处理?
这里以html_template类为例, 查看代码可以得知, 该类的process接口内部可能会抛两种异常, 这两种异常都是其基于stl::的标准异常类派生出来的异常类, 分别是syntax_ex和runtime_ex, 特别的, 两个异常类内部还包含了一些额外的辅助信息, 那么可以用如下代码处理该异
常,注意, what接口是stl的异常基类里面默认提供的.
库里面的定义的异常类代码:
- 101 //! template syntax exception class
- 102 class syntax_ex : public std::runtime_error
- 103 {
- 104 public:
- 105 //! path to template that caused the error
- 106 std::string template_path;
- 107
- 108 //! problem line
- 109 size_t line;
- 110 //! error detail
- 111 std::string detail;
- 112
- 113 //! ctructor
- 114 syntax_ex(const std::string & str_what) :
- 115 std::runtime_error(str_what)
- 116 {
- 117 detail = "";
- 118 line = 0;
- 119 }
- 120
- 121 //! dtructor
- 122 ~syntax_ex() throw() {}
- 123 };
- 65 // 下面代码来自 std::runtime_error
- /** Returns a C-style character string describing the general cause of
- 66 * the current error (the same string passed to the ctor). */
- 67 virtual const char*
- 68 what() const throw();
- try
- {
- strHtml = templ.Process();
- }
- catch (runtime_ex& e)
- {
- error_log( "throw runtime_ex in Process(), msg: %s"
- "template_path: %s",
- e.what(),
- e.template_path.c_str()
- );
- }
- catch (syntax_ex& e)
- {
- error_log( "throw syntax_ex in Process(), msg: %s"
- "template_path: %s"
- "line : %d "
- "detail : %s ",
- e.what(),
- e.template_path.c_str(),
- e.line,
- e.detail.c_str()
- );
- }
如果
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)
{
}
}