Espacios de nombres
Variantes
Acciones

Bloque try

De cppreference.com
< cpp‎ | language

Asocia uno o más controladores de excepciones (cláusulas catch) con una instrucción compuesta.

Contenido

[editar]Sintaxis

tryinstrucción-compuestasec-de-controladores

donde la sec-de-controladores es una secuencia de uno o más controladores que tiene la sintaxis siguiente:

catch(atrib (opcional)sec-especificadores-de-tipodeclarador)instrucción-compuesta (1)
catch(atrib (opcional)sec-especificadores-de-tipodeclarador-abstracto (opcional))instrucción-compuesta (2)
catch(...)instrucción-compuesta (3)
instrucción-compuesta - secuencia de instrucciones encerrada entre llaves
atrib(desde C++11) - lista opcional de atributos, se aplica al parámetro formal
sec-especificadores-de-tipo - parte de una declaración de parámetro formal, lo mismo que en una lista de parámetros de función
declarador - parte de una declaración de parámetro formal, lo mismo que en una lista de parámetros de función
declarador-abstracto - parte de un declaración de parámetro formal sin denominación, lo mismo que en una lista de parámetros de función
1) La cláusula catch que declara un parámetro formal denominado
try{/* */}catch(conststd::exception& e){/* */}
2) La cláusula catch que declara un parámetro sin denominación
try{/* */}catch(conststd::exception&){/* */}
3) Cláusula catch general, que se activa para cualquier excepción
try{/* */}catch(...){/* */}

[editar]Explicación

Véase lanzamiento de excepciones para mayor información sobre expresiones de lanzamiento.

Un bloque try es una instrucción, y como tal, puede aparecer en cualquier lugar donde pueda aparecer una instrucción (es decir, como una de las intrucciones en una instrucción compuesta, incluida la instrucción compuesta del cuerpo de la función). Véase bloque try de función para los bloques try alrededor de los cuerpos de funciones. La siguiente descripción se aplica tanto a los bloques try como a los bloques try de función.

El parámetro formal de la cláusula catch (sec-especificadores-de-tipo y declarador o sec-especificadores-de-tipo y declarador-abstracto) determina qué tipos de excepciones hacen que se ingrese a esta cláusula catch. No puede ser un tipo de referencia rvalue,(desde C++11) un tipo clase abstracta, un tipo incompleto, o puntero a tipo incompleto (excepto que punteros a void (que pueden estar calificados-cv) están permitidos). Si el tipo del parámetro formal es tipo de array o tipo de función, se trata como el tipo puntero correspondiente (similar a una declaración de función).

Cuando se lanza una excepción por cualquier instrucción en instrucción-compuesta, el objeto excepción de tipo E se compara con los tipos de los parámetros formales T de cada cláusula catch en sec-de-controladores, en el orden en que se enumeran las cláusulas catch. La excepción es una coincidencia si se cumple alguna de las siguientes condiciones:

  • E y T son del mismo tipo (ignorando los calificadores-cv de nivel superior en T);
  • T es una referencia lvalue (que puede estar calificada-cv) a E;
  • T es una clase base pública inequívoca de E;
  • T es una referencia a una clase base pública inequívoca de E;
  • T es (puede estar calificado-cv) U o const U &(desde C++14), y U es un puntero o puntero a tipo miembro, y E también es un tipo de puntero o puntero a tipo miembro que es implícitamente convertible a U por uno o más de:
* una conversión de puntero estándar que no sea a una clase base privada, protegida o ambigua;
* una conversión de calificación;
* una conversión de puntero de función;
(desde C++17)
  • T es un puntero o un puntero a miembro o una referencia a un puntero constante(desde C++14), mientras que E es std::nullptr_t.
try{ f();}catch(conststd::overflow_error& e){// esto se ejecuta si f() lanza std::overflow_error (regla de mismo tipo)}catch(conststd::runtime_error& e){// esto se ejecuta si f() lanza std::underflow_error (regla de clase base)}catch(conststd::exception& e){// esto se ejecuta si f() lanza std::logic_error (regla de clase base)}catch(...){// esto se ejecuta si f() lanza std::string o int o cualquier otro tipo no relacionado}

La cláusula general catch(...) coincide con las excepciones de cualquier tipo. Si está presente, debe ser la última cláusula catch en la sec-de-controladores. El bloque catch general se puede usar para garantizar que ninguna excepción no capturada pueda escapar de una función que ofrece la garantía de excepción de no lanzamiento.

Si no se encuentran coincidencias después de examinar todas las cláusulas catch, la propagación de excepción continúa hasta el bloque try que lo contiene, como se describe en la expresión de lanzamiento. Si no quedan bloques try que los contenga, se ejecuta std::terminate (en este caso, se define por la implementación si se produce algún desenredo de la pila: se permite lanzar una excepción no atrapada para terminar el programa sin invocar ningún destructor).

Al ingresar a una cláusula catch, si su parámetro formal es una clase base del tipo de excepción, es inicializada mediante la inicialización de copia desde el subobjeto de la clase base del objeto de excepción. De lo contrario, se inicializa por medio de la inicialización de copia desde el objeto de excepción (esta copia está sujeta a la elisión de copia).

try{std::string("abc").substr(10);// lanza std::length_error}// catch (std::exception e) // inicialización de copia desde la base std::exception// {// std::cout << e.what(); // información sobre length_error se perdió// }catch(conststd::exception& e)// referencia a base de un objeto polimorfo{std::cout<< e.what();// información de length_error se imprime}

Si el parámetro de la cláusula catch es un tipo referencia, cualquier cambio realizado en él se refleja en el objeto de excepción, y puede observarse por otro controlador si la excepción se vuelve a lanzar con throw;. Si el parámetro no es una referencia, cualquier cambio realizado en él es local y su duración termina cuando el controlador termina.

Dentro de una cláusula catch, std::current_exception puede usarse para capturar la excepción en un std::exception_ptr, y std::throw_with_nested puede ser usada para construir excepciones anidadas.(desde C++11)

No se usará un instrucción goto o switch para transferir el control a un bloque try o a un controlador.

Aparte de lanzar o volver a lanzar la excepción, la cláusula catch después de un bloque try normal (no un bloque try de función) puede salir con una instrucción return, continue, break, goto, o llegar al final de su instrucción-compuesta. En cualquier caso, esto destruye el objeto de excepción (a menos que exista una instancia de std::exception_ptr que se refiera a él).

[editar]Notas

No se garantiza que la expresión de lanzamiento throwNULL; coincida con una cláusula catch de puntero, porque el tipo de objeto de excepción puede ser int, pero throw nullptr; seguramente se corresponde con cualquier cláusula catch de puntero o de puntero a miembro.

Si se coloca una cláusula catch para una clase derivada después de la cláusula catch para una clase base, la cláusula catch de la derivada nunca se ejecutará.

try{ f();}catch(conststd::exception& e){// se ejecutará si f() lanza std::runtime_error}catch(conststd::runtime_error& e){// ¡código muerto!}

Si se utiliza goto para salir de un bloque try y si alguno de los destructores de variables automáticas con ámbito de bloque que se ejecutan por la instrucción goto arroja excepciones, esas excepciones se atrapan por los bloques try en los que se definen las variables:

label:try{ T1 t1;try{ T2 t2;if(condition)goto label;// destruye a t2, luego destruye a t1, luego salta a la etiqueta}catch(...){}// atrapa la excepción del destructor de t2}catch(...){}// atrapa la excepción del destructor de t1

[editar]Palabras clave

try, catch, throw

[editar]Ejemplo

El siguiente ejemplo demuestra varios usos del bloque try

#include <iostream>#include <vector>   int main(){try{std::cout<<"Lanzando una excepción de un entero...\n";throw42;}catch(int i){std::cout<<" la excepción del entero se atrapo, con valor: "<< i <<'\n';}   try{std::cout<<"Creando un vector con 5 elementos... \n";std::vector<int> v(5);std::cout<<"Accediendo al onceavo elemento del vector...\n";std::cout<< v.at(10);// vector::at() lanza std::out_of_range}catch(conststd::exception& e)// atrapado por referencia a la base{std::cout<<" se atrapo una excepción estándar, con mensaje '"<< e.what()<<"'\n";}   }

Posible salida:

Lanzando una excepción de un entero... la excepción del entero se atrapo, con valor: 42 Creando un vector con 5 elementos... Accediendo al onceavo elemento del vector... se atrapo una excepción estándar, con mensaje 'out_of_range'

[editar]Defect reports

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
CWG 98 C++98 una instrucción switch podía transferir el control a un bloque try
o aun controlador
prohibido
CWG 210 C++98 la expresión throw se comparaba con las cláusulas catch el objecto excepción se compara
con las cláusulas catch
CWG 1166 C++98 no se especificó el comportamiento cuando coincide una cláusula catch
cuyo tipo de excepción en una referencia a un tipo de clase abstracta
no se permiten los tipos de clase
abstracta para las cláusulas catch
CWG 1769 C++98 cuando el tipo de excepción declarado en la cláusula catch es una
base del tipo del objeto de excepción, se podría usar un constructor
de conversión para la inicialización del parámetro de la cláusula catch
el parámetro se inicializa mediante
copia desde el subobjeto de clase
base correspondiente del objeto
de excepción
CWG 2093 C++98 un objeto excepción de puntero a tipo objeto no podía coincidir con un
controlador de puntero a tipo objeto mediante la conversión de calficación
permitido
close