这是一个例子:
#include <iostream> using namespace std; class Exception { public: virtual void print() { cout << "Exception" << endl; } }; class IllegalArgumentException : public Exception { public: virtual void print() { cout << "IllegalArgumentException" << endl; } }; int main(int argc,char **argv) { try { IllegalArgumentException i; Exception& ref = i; cout << "ref.print: "; ref.print(); throw ref; } catch(Exception& e) { cout << "catched: "; e.print(); } }
此示例的输出是:
ref.print: IllegalArgumentException catched: Exception
使用引用将导致所使用的派生类的print方法.在try块中,引用确实使用它.为什么不抓住异常&像一个IllegalArgumentException一样,我该如何得到这个行为?
以下代码似乎做了它应该做的事情:
try { IllegalArgumentException i; Exception* pointer = &i; throw pointer; } catch(Exception* e) { cout << "pointer catched: "; e->print(); }
但是在try块的范围之外,指针是否变得可能无效?那么这样做是有风险的,如果我在堆上分配内存来解决这个问题,我有责任在catch块内删除不漂亮的东西.那么你如何解决这个问题呢?
解决方法
A throw-expression initializes a temporary object,called the exception object,the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from “array of
T
” or “function returningT
” to “pointer toT
” or “pointer to function returningT
”,respectively. The temporary is an lvalue and is used to initialize the variable named in the matching handler. If the type of the exception object would be an incomplete type or a pointer to an incomplete type other than (possibly cv-qualified)void
the program is ill-formed. Except for these restrictions and the restrictions on type matching mentioned in 15.3,the operand ofthrow
is treated exactly as a function argument in a call or the operand of a return statement.
我已经看到了一些代码库,通过抛出指向异常的指针,而不是直接对象来解决这个问题,但是我个人只是重新考虑你的“需要”来做到这一点.