2010-03-26 12 views
67

Duplicar posible:
catch exception by pointer in C++C++ catch blocks: captura la excepción por valor o referencia?

siempre capturar las excepciones por valor. por ejemplo

try{ 
... 
} 
catch(CustomException e){ 
... 
} 

Pero me encontré con un código que tenía lugar catch(CustomException &e) lugar. ¿Es esto a) bien b) mal c) un área gris?

+0

Tenga en cuenta que la referencia correcta también es constante: 'catch (CustomException const & e)' ... –

+1

No debe marcarse como duplicado - captura la excepción por ptr es diferente a la captura por referencia o valor. – wcochran

Respuesta

103

La práctica habitual de excepciones en C++ es ...

tiro por el valor, la captura por referencia

La captura de valor es problemático en la cara de las jerarquías de herencia. Suponga, para su ejemplo, que existe otro tipo MyException que hereda de CustomException y anula elementos como un código de error. Si se arrojó un tipo MyException, su bloque de captura provocaría que se convirtiera en una instancia CustomException que provocaría el cambio del código de error.

Referencias

+4

A esto yo agregaría: catch by const reference. Desafortunadamente puedes lanzar un objeto const y atraparlo con una referencia no const. Para evitar este "rechazo" silencioso de const, siempre capture una referencia constante, y asegúrese de que sus tipos de excepción tengan acceso directo correcto. –

+20

@Danial Earwicker: ¿Por qué es "desafortunado" que pueda atrapar a través de una referencia no constante? El objeto de excepción siempre se copia, así que cualquier "objeto" que arrojes, no puedes afectar el original de ningún bloque catch ya que el "objeto" lanzado realmente era solo un inicializador. No hay rechazo de const; Los objetos de excepción siempre son no const, no volátiles. Permitir una captura mediante referencia no constante permite que los bloques de captura intermedios agreguen información a la excepción. No se usa comúnmente, pero está ahí si lo necesitas. –

+0

Puede proporcionar una referencia, si desea la respuesta aceptada :) –

20

La captura por valor será slice objeto de excepción si la excepción es de tipo derivado al tipo que captura.

Esto puede o no ser importante para la lógica en su bloque de captura, pero hay pocas razones para no atrapar por referencia de referencia.

Tenga en cuenta que si throw; sin un parámetro en un bloque catch, se vuelve a lanzar la excepción original, ya sea que capture o no una copia cortada o una referencia al objeto de excepción.

+6

No estoy familiarizado con el término * slice * en este contexto. –

+6

Creo que "slice" es un término que a las personas que están acostumbradas a usar los lenguajes de referencia les gusta usar. La idea es "cortar" parte del objeto si asigna un objeto derivado a su tipo base, lo que a mí me parece una manera engañosa de mirarlo porque lo que realmente está sucediendo es eso en el operador de asignación de copiado de la clase base ' base & operator = (const base & other) 'el objeto derivado se convierte implícitamente en una referencia' base & ', por lo que la tarea trata a la clase derivada igual que a la clase base.no hay magia para dividir o transferir cosas, estás llamando a una función – Injektilo

8

A menos que quiera jugar con la excepción, por lo general debe utilizar una referencia constante: catch (const CustomException& e) { ... }. El compilador se ocupa de la vida útil del objeto arrojado.

2

se crea en (CustomException e) nuevo objeto de CustomException ... así que es constructor se llama mientras que en (CustomException & e) se acaba la referencia ... no es nuevo objeto se crea y ningún constructor se llama ... tan formal es un poco sobrecargado ... más tarde es mejor usar ...

Cuestiones relacionadas