c++ - with - Usando `throw;` en una excepción modificada
throw exception with error code c# (5)
Tengo una función
foo
que puede lanzar una excepción de
bar
.
En otra función, llamo
foo
pero tengo la capacidad de agregar más detalles a la excepción de la
bar
si se lanza.
(Prefiero no pasar esa información como parámetro a
foo
ya que realmente no pertenece allí debido a la naturaleza genérica de esa función).
Entonces hago esto en la persona que llama:
try {
foo();
} catch (bar& ex){
ex.addSomeMoreInformation(...);
throw;
}
throw
volver a lanzar la excepción modificada o necesito usar
throw ex;
?
Este último presumiblemente tomaría una copia de valor, así que prefiero no hacer eso.
¿
throw
tomar una copia de valor también?
Sospecho que no lo haría.
(Soy consciente de que podría verificar, pero me preocupa tropezar con una construcción no especificada o indefinida, por lo que me gustaría saber con certeza).
C ++ 11 §15.1 / 8:
" Una expresión de lanzamiento sin operando vuelve a lanzar la excepción manejada actualmente (15.3). La excepción se reactiva con el temporal existente; no se crea un nuevo objeto de excepción temporal.
En este caso, debe usar
throw
para obtener el comportamiento deseado ... es decir, throw arrojaría la excepción modificada ya que la excepción fue capturada por referencia.
Permítanme tratar de hacer una diferencia explícita entre estos lanzamientos a través de ejemplos:
class exception
{
};
class MyException : public exception
{
};
void func()
{
try
{
throw MyException();
}
catch( exception& e )
{
//do some modification.
throw; //Statement_1
throw e; //Statement_2
}
}
Declaración_1: -
Lo que hace es simplemente volver a lanzar cuál es la excepción actual, es decir, no hace más copias (como se hizo cuando se lanzó la excepción inicialmente). Entonces, si realiza algún cambio en la excepción detectada aquí ... también estaría allí en la rutina de la persona que llama.
Declaración_2: -
Esto arroja la "excepción" que originalmente se detectó como MyException, es decir, volvería a hacer la copia. Por lo tanto, solo olvídate de los cambios que hiciste, ni siquiera pasará o * una excepción ginal a la persona que llama. Lanza una "excepción" a la rutina de la persona que llama.
Espero ser lo suficientemente claro (y DERECHO EN LA PISTA DE C ++) ...
En realidad, el estándar es muy preciso aquí. [excepto manija] / 17:
Cuando el controlador declara una referencia a un objeto no constante, cualquier cambio en el objeto al que se hace referencia son cambios en el objeto temporal inicializado cuando se ejecutó la expresión de lanzamiento y tendrá efecto si ese objeto se vuelve a lanzar .
Y [excepto tirar] / 8:
Una expresión de lanzamiento sin operando vuelve a lanzar la excepción manejada actualmente (15.3).
de acuerdo con this , lanzar excepciones en c ++ se puede hacer de dos maneras:
- tirar expresión : primero, copiar-inicializa el objeto de excepción de la expresión (esto puede llamar al constructor de movimiento para la expresión de valor, y la copia / mover puede estar sujeto a copia de elisión), luego transfiere el control al controlador de excepción con el tipo correspondiente cuyo compuesto la declaración o la lista de inicializador de miembros se ingresó más recientemente y este hilo de ejecución no la salió.
- throw : vuelve a lanzar la excepción manejada actualmente. Abandona la ejecución del bloque catch actual y pasa el control al siguiente controlador de excepciones coincidente (pero no a otra cláusula catch después del mismo bloque try: se considera que su declaración compuesta ha sido ''salida''), reutilizando el objeto de excepción existente: No se hacen nuevos objetos. Este formulario solo está permitido cuando actualmente se está manejando una excepción (llama a std :: terminate si se usa de otra manera). La cláusula catch asociada con un bloque de prueba de función debe salir por relanzamiento si se usa en un constructor.
Para subrayar mi respuesta, tirar debería estar bien en tu caso.
throw
(sin un objeto de excepción) volverá a lanzar la excepción actual.
(debe estar dentro del bloque catch, de lo contrario se llama
std::terminate
).
Debido a que cambió la referencia del objeto de excepción actual, no necesita lanzar explícitamente el objeto y
lanzar nuevamente la excepción modificada
y no se crea ningún nuevo objeto temporal.