En ambos casos, dado que captura por referencia, está alterando efectivamente el estado del objeto de excepción original (que puede pensar que reside en una ubicación de memoria mágica que seguirá siendo válida durante el desenrollado posterior , 0x98e7058
en el ejemplo siguiente). Sin embargo,
- En el primer caso, ya que volver a lanzar con
throw;
(que, a diferencia de throw err;
, preserva el objeto de excepción original, con sus modificaciones, en dicha "lugar mágico" a 0x98e7058
) va a reflejar la llamada a modo de adición ()
- En el segundo caso, dado que arroja algo explícitamente, se creará una copia de y
err
luego se lanzará de nuevo (en una "ubicación mágica" diferente 0x98e70b0
, porque por lo que el compilador sabe, err
podría haber un objeto en la pila a punto de desenrollarse, como e
fue en 0xbfbce430
, no en la "ubicación mágica" en 0x98e7058
), por lo que perderá datos específicos de la clase derivada durante la construcción de la copia de una instancia de clase base.
Programa simple para ilustrar lo que está sucediendo:
#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;
}
Resultado:
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
Ver también: