2010-03-08 7 views
5

Actualmente estoy usando Visual Studio Express C++ 2008 y tengo algunas preguntas sobre la captura de pedidos de bloques. Lamentablemente, no pude encontrar la respuesta en Internet, por lo que planteo estas preguntas a los expertos.Preguntas sobre el orden de las declaraciones de captura en el bloque catch - compilador específico o estándar de lenguaje?

Noté que a menos que la captura (...) se coloque al final de un bloque catch, la compilación fallará con el error C2311. Por ejemplo, la siguiente sería compilar:

catch (MyException) 
{ 
} 
catch (...) 
{ 
} 

mientras que el siguiente no lo haría:

catch (...) 
{ 
} 
catch (MyException) 
{ 
} 

a. ¿Podría preguntar si esto está definido en el estándar de lenguaje C++, o si esto es solo el compilador de Microsoft siendo estricto?

b. Do C# y Java también tienen las mismas reglas?

c. Como un lado, también he intentado hacer una clase base y una clase derivada, y poner la instrucción catch para la clase base antes de la instrucción catch para la clase derivada. Esto compilado sin problemas. ¿No hay normas lingüísticas que protejan contra dicha práctica, por favor?

+0

Re (B): la sección 8.10 de la especificación C# proporciona una descripción detallada de cómo funciona esto en C#. Véalo para más detalles. Re (C) que es ilegal en C#. Ver la sección 8.10 para más detalles. –

Respuesta

5

De acuerdo con la norma, el pedido es significativo. Básicamente, se capturará la primera captura que coincida con la excepción.

a) Debido a que catch(...) hará que las siguientes capturas sean irrelevantes, la norma solo permite que sea la última captura.

b) C# y Java tienen reglas similares.

c) la captura (por referencia o puntero) de una base antes de una clase derivada hará que el código para el derivado sea irrelevante. Sin embargo, el estándar no permite esto

+0

a) es verdadero (las dos primeras oraciones). catch (...) es especial porque ninguna cláusula posterior podría coincidir, por lo que las cláusulas posteriores están completamente prohibidas. –

+0

Reformulado según estos dos comentarios. Gracias Johannes y Ben –

3

De C++ estándar 15.3/5 "Manejo de una excepción":

Los manejadores de un bloque try son juzgados por orden de aparición. Eso hace posible escribir manejadores que nunca se pueden ejecutar, por ejemplo colocando un manejador para una clase derivada después de un manejador para una clase base correspondiente.

A ... en una declaración de excepción de manejador funciona de manera similar a ... en una declaración de parámetro de función; especifica una coincidencia para cualquier excepción. Si está presente, un controlador ... será el último controlador para su bloque try.

+1

¿Alguna idea de por qué el estándar no lo prohíbe? Parece una trampa estúpida que es fácil de evitar al hacerlo mejor. –

+0

Michael, gracias por tu respuesta. Johannes, gracias por la pregunta, esto es lo que me pregunto también. – Andy

+0

@litb: ninguna idea en absoluto. Me interesaría recibir un comentario de cualquiera que lo supiera (o tuviera una buena idea). –

3

El denominado controlador predeterminado catch(...) debe ser el último controlador en la lista de controladores. Esto es de hecho requerido por el estándar. Sin embargo, este requisito es específico del controlador predeterminado. De lo contrario, la norma no restringe el orden de los controladores, lo que significa que generalmente puede crear un controlador que "interceptaría" todas las excepciones que de otro modo llegarían a algún otro controlador.

Por otra parte, es perfectamente legal para repetir la misma cláusula catch (con el mismo tipo) varias veces

catch (int) { 
    // ... 
} 
catch (int) { 
    // ... 
} 

a pesar de que sólo el primero de ellos tendrá la oportunidad de volver a pescar nada. Un buen compilador emitirá una advertencia para casos como ese, pero formalmente no es un error.

+0

Gracias. ¡No sabía que puede tener dos declaraciones de captura que capturen exactamente el mismo tipo de datos! – Andy

Cuestiones relacionadas