2011-04-21 18 views
14

Esta fue una pregunta de entrevista mía.excepción manejo de un constructor

Sorprendentemente Nunca había pensado en esta pregunta un poco a mí mismo.

¿Podemos tener manejo de excepciones dentro de un constructor C++?

en tiempo verbal y no pensaba mucho, dije "sí, probablemente podríamos hacerlo en un constructor.leturas dicen que estamos asignando algo de memoria utilizando un nuevo operador a un miembro del puntero y arroja una mala excepción de asignación, de esta manera hay una posibilidad de excepciones, habiendo resucitado"

Luego, más tarde pensé que los constructores no pueden devolver un value.So ¿cómo una excepción dentro de un constructor caught.now que estoy pidiendo esto a mí mismo!

¿Alguien puede ayudarme a salir de esta confusión?

+0

Usted podría detectar la excepción en el código de llamada, no en el constructor. – helpermethod

+3

Las excepciones no se devuelven de la misma forma que los valores de retorno, saltan la pila al primer bloque catch apropiado, por lo que aunque no se puede devolver un valor del constructor, se puede lanzar una excepción. – forsvarir

+0

@Helper Método: si hubiera asignado memoria en el constructor definitivamente querría atrapar la excepción en el constructor para poder desasignar la memoria (y luego probablemente volver a lanzarla). Pero es más inteligente que el objeto aloje dinámicamente como máximo un objeto, por lo que no es necesario hacer este tipo de limpieza manual. –

Respuesta

12

Ver esta pregunta GOTW Constructor Failures que se ocupa de su consulta un poco y llega a decir que es una pérdida de tiempo.

+3

+1 Iba a escribir sobre el function-try-block como una opción y sus muchos defectos, pero no me acercaría a la descripción de Sutter :) –

+0

Ese fue un artículo muy interesante, def +1 – Justin

-2

C++ tiene cláusulas try-catch similares a las de otros idiomas. Un tutorial se puede encontrar en línea: http://www.cplusplus.com/doc/tutorial/exceptions/

EDIT: se convirtió en ejemplo de código totalmente funcional

#include <iostream> 
using namespace std; 

class A 
{ 
public: 
    void f(){ 
    throw 10; 
    } 

    A(){ 
    try{ 
     f(); 
    } 
    catch(int e){ 
     cout << "Exception caught\n"; 
    } 
    } 
}; 

int main (int argc, const char * argv[]) 
{ 

    A a; 
    return 0; 
} 

Esto produce una salida:

Exception caught 
+0

@ laas.i sé que hay muchos documentos. Pero estoy particularmente preguntando sobre el manejo de excepciones en un constructor. Esto no responde a mi pregunta. – Vijay

+0

C++ no tiene bloques 'finally', y el manejo de excepciones en C++ difiere en muchos aspectos de lenguajes como Java, por ejemplo. Para la limpieza, C++ utiliza http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization – helpermethod

+0

@Helper Method - usted Por supuesto, tienen razón sobre 'finalmente', pero según tengo entendido, @zombie preguntó sobre el manejo de excepciones ** en el interior de los constructores, así que mi ejemplo sigue siendo válido o la pregunta debe corregirse. Actualizo mi respuesta con más código. – Laas

2

constructores no tienen un tipo de retorno, por lo tanto, no es posible utilizar los códigos de retorno . La mejor forma de señalar error de constructor es por lo tanto a lanzar una excepción. Si no tiene la opción de usar excepciones, el "menos malo" problema de es poner el objeto en un estado "zombie" por configurando un bit de estado interno para que el objeto actúe como si fuera muerto aunque técnicamente sigue siendo vivo.

Detectará la excepción en el código de llamada, no en el constructor.

Ver How can I handle a constructor that fails? para más detalles (en realidad, me gustaría sugerir la lectura de la página entera sobre el manejo de excepciones, verdaderamente esclarecedor).

+0

He leído esto. Pero estoy esperando algunos métodos prácticos que las personas usan en este tipo de escenarios. – Vijay

+1

+1, aunque hay que decir que la pregunta también es un truco. Mientras que normalmente solo arrojas dentro de un constructor cuando falla de alguna manera, es perfectamente posible intentar capturar dentro de un constructor para manejar otras fallas y evitar el fallo de dicho constructor en primer lugar (o, volver a lanzar). Dependiendo de la situación, esto puede ser preferible. Por ejemplo, si construyes dos objetos en tu constructor, y el segundo arroja bad_alloc, ¿qué haces? Al capturar la excepción en el código de llamada se filtrará el primer objeto. El manejo dentro del constructor evita esto. – Damon

+0

@zombie: ¿qué escenarios? una excepción lanzada desde un constructor? ¿Una falla del constructor? Un constructor atrapando excepciones? – forsvarir

0

El manejo de excepciones y el tipo de devolución son completamente diferentes. cuando el programa encuentra la excepción en el constructor, arroja la excepción a casi by catch block [si se usa] o se lanza a la persona que llama (main()). en este caso, tenemos catch block en constructor y excepción manejada por él. Una vez que se maneje la excepción, la instrucción restante en el constructor/función comenzará a ejecutarse. vea el ejemplo siguiente,

class A 
{ 
    public: 
    A(){ 
     printf("Hi Constructor of A\n");   
    try 
    { 
     throw 10; 
    } 
    catch(...) 
    { 
     printf("the String is unexpected one in constructor\n"); 
    } 
    printf("Hi Constructor of A\n"); 
} 
    ~A(){ 
    printf("Hi destructor of A\n"); 
} 
}; 

int main() 
{ 

try{ 
    A obj ; 
    throw "Bad allocation"; 
} 
catch(int i) 
{ 
    printf("the Exception if Integer is = %d\n", i); 
} 
catch(double i) 
{ 
    printf("the Exception if double is = %f\n", i); 
} 
catch(A *objE) 
{ 
    printf("the Exception if Object \n"); 
} 
catch(...) 
{ 
    printf("the Exception if character/string \n"); 
} 
printf("Code ends\n"); 
return 0; 
} 

Este producto Salida:

Start: Constructor of A 
the String is unexpected one in constructor 
End: Constructor of A 
Hi destructor of A 
the Exception if character/string 
Code ends 
Cuestiones relacionadas