C ++exception问题重新抛出原始exception

catch中的append()是否会导致重新抛出的exception,以查看append()被调用的效果?

try { mayThrowMyErr(); } catch (myErr &err) { err.append("Add to my message here"); throw; // Does the rethrow exception reflect the call to append()? } 

同样,如果我用这种方法重写它,如果实际的exception是由myErr派生的,会不会发生位切片?

 try { mayThrowObjectDerivedFromMyErr(); } catch (myErr &err) { err.append("Add to my message's base class here"); throw err; // Do I lose the derived class exception and only get myErr? } 

在这两种情况下,由于您通过引用来捕获,所以您正在有效地改变原始exception对象的状态(您可以将其视为驻留在后续展开期间保持有效的神奇内存位置 – 下0x98e7058中的0x98e7058 ) 。 然而,

  1. 在第一种情况下,因为你抛出重throw; (与throw err;不同,它保留了原来的exception对象,并且在你的修改中,在0x98e7058 “神奇的位置”) 将会反映对append()
  2. 在第二种情况下,由于你明确地抛出了一些东西,所以会创build一个err副本 ,然后重新抛出(在一个不同的“神奇的位置” 0x98e70b0 – 因为所有的编译器知道err可能是堆栈上的一个对象, ,就像e是在0xbfbce430 ,而不是在0xbfbce430的“神奇的位置”),所以在复制基类实例的过程中你将失去派生类特定的数据

简单的程序来说明发生了什么事情:

 #include <stdio.h> struct MyErr { MyErr() { printf(" Base default constructor, this=%p\n", this); } MyErr(const MyErr& other) { printf(" Base copy-constructor, this=%p from that=%p\n", this, &other); } virtual ~MyErr() { printf(" Base destructor, this=%p\n", this); } }; struct MyErrDerived : public MyErr { MyErrDerived() { printf(" Derived default constructor, this=%p\n", this); } MyErrDerived(const MyErrDerived& other) { printf(" Derived copy-constructor, this=%p from that=%p\n", this, &other); } virtual ~MyErrDerived() { printf(" Derived destructor, this=%p\n", this); } }; int main() { try { try { MyErrDerived e; throw e; } catch (MyErr& err) { printf("A Inner catch, &err=%p\n", &err); throw; } } catch (MyErr& err) { printf("A Outer catch, &err=%p\n", &err); } printf("---\n"); try { try { MyErrDerived e; throw e; } catch (MyErr& err) { printf("B Inner catch, &err=%p\n", &err); throw err; } } catch (MyErr& err) { printf("B Outer catch, &err=%p\n", &err); } return 0; } 

结果:

  Base default constructor, this=0xbfbce430 Derived default constructor, this=0xbfbce430 Base default constructor, this=0x98e7058 Derived copy-constructor, this=0x98e7058 from that=0xbfbce430 Derived destructor, this=0xbfbce430 Base destructor, this=0xbfbce430 A Inner catch, &err=0x98e7058 A Outer catch, &err=0x98e7058 Derived destructor, this=0x98e7058 Base destructor, this=0x98e7058 --- Base default constructor, this=0xbfbce430 Derived default constructor, this=0xbfbce430 Base default constructor, this=0x98e7058 Derived copy-constructor, this=0x98e7058 from that=0xbfbce430 Derived destructor, this=0xbfbce430 Base destructor, this=0xbfbce430 B Inner catch, &err=0x98e7058 Base copy-constructor, this=0x98e70b0 from that=0x98e7058 Derived destructor, this=0x98e7058 Base destructor, this=0x98e7058 B Outer catch, &err=0x98e70b0 Base destructor, this=0x98e70b0 

另请参阅:

  • C ++中的exception对象范围
  • 投掷…“参考”

是的,重新抛出重新抛出原来的exception对象,你通过引用修改了它。 你也可以捕获一个基类的引用,修改它,仍然能够通过throw;重新抛出原始派生的exceptiontypesthrow;

对于第一个问题,是的。

但第二,请参考弗拉德的答案。 您将需要仔细devise您的例外对象来处理复制ctor。 按照惯例,基类不承认它的孩子,所以你很可能会失去派生类所携带的额外数据。