2012-04-21 14 views
5

estoy usando QT 4.8 (C++) para el proyecto de aplicación de escritorio, y escribir el manejo de excepciones es el siguiente:¿Cómo evitar escribir código repetido en bloques catch?

void callerMethod() 
{ 
    try 
    { 
    method1(); 
    } 
    catch(Exception1& e) 
    { 
    // display critcal error message 
    // abort application 
    } 
    catch(std::Exception& e) 
    { 
    // print exception error message 
    } 
    catch(...) 
    { 
    // print unknown exception message 
    } 
} 

void method1() 
{ 
    try 
    { 
    // some initializations 
    // some operations (here exceptions can occur) 
    // clean-up code (for successful operation i.e no exception occurred) 
    } 
    catch(Exception1& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(Exception2& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(Exception3& e) 
    { 
    // clean-up code 
    throw e; 
    } 
    catch(...) 
    { 
    // clean-up code 
    throw; 
    } 
} 

Así que mi pregunta qué tengo que escribir el código de limpieza en cada bloque catch ? ¿Hay alguna manera de que pueda evitar escribir código repetido?

NOTA :: [En metodo1()] Quiero volver a arrojar excepciones que se produjeron a mi caller.So No puedo atraparlos en un solo bloque catch, ya continuación, escriba la información se perderá .

+4

Probar t o reducir la cantidad de código de limpieza necesario mediante el uso de punteros inteligentes, clases de contenedores, etc. Idealmente, no debería haber ningún código de limpieza. – user763305

+0

Parece que lo que quieres hacer es simplemente 'try {/ * throw * /} catch (specific_exception const & e) {/ * terminate * /}'. Si no le importan los tipos de excepción 'Exception1',' Exception2' y demás, entonces * do not * catch them. –

+1

Además, incluso si capta por referencia, * debería * volver a generar usando 'throw;' en lugar de 'throw e;' para evitar cortar. – ereOn

Respuesta

8

Método1 puede ser mucho más simplificado por dos conceptos:

  1. RAII. Ponga cualquier código de limpieza en destructores, y el código de limpieza estará centralizado.
  2. Utilice el throw no calificado, y no tendrá que saber sobre el tipo de excepción lanzada.

Así, method1() debe verse como:

void method1() 
{ 
    // some initializations of RAII objects 
    // some operations (here exceptions can occur) 
} 

La primera cláusula en catchcallerMethod se puede quitar si usted deriva Exception1 de std::exception, ya que el método what() es virtual.

+1

+1. Yo quería decir eso. RAII es la solución aquí. – Nawaz

+0

Pero quiero manejar Exception1 por separado en callerMethod(). Si se produjo Exception1, quiero abortar la aplicación. – EngineeredBrain

+0

@AnwarShaikh: Todavía puedes hacer eso. RAII resuelve solo su problema de limpieza. – Nawaz

0

Si todo el código que su limpieza es totalmente idéntica, se puede hacer todo en su captura (...) bloques:

try { 
    // code 
} catch (...) { 
    // cleanup 
    throw; 
} 

Si el código varía ligeramente, siempre puede llamar a una función de limpieza:

try { 
    // code 
} catch (exc1 ex) { 
    cleanup(args); 
    // exc1 specific 
    throw; 
} catch (exc2 ex) { 
    cleanup(args); 
    // exc2 specific 
    throw; 
} catch (...) { 
    cleanup(args); 
    throw; 
} 
+0

Si escribo sola captura (..) qué arrojar excepción, entonces, en el método llamante ¿Cómo sabré qué excepción se produjo? Porque quiero manejar Exception1 que aborta la aplicación. – EngineeredBrain

1

Debe tirar las excepciones lo más bajo posible y atraparlas lo más alto posible en la cadena de llamadas. Esto conduce automáticamente a una menor duplicación de código y centraliza el manejo de errores. Estás arrojando/atrapando a todos en un solo lugar, lo que parece un poco ... forzado.

hago a menudo este tipo de cosas (especialmente para las excepciones de fin de programa:.

int main() 
try 
{ 
    function_calls_that_may_throw(); 
    // ... 
} 
catch(my_exception& e) 
{ 
    e.do_exception_stuff(); 
} 
catch(std::exception& e) 
{ 
    std::cout << e.what(); 
} 
catch(...) 
{ 
    std::cout << "Something bad happened.\n"; 
} 

Esto sólo es posible por lanzar excepciones que no piensa en el manejo de mejor o volver a intentar la operación fallida o algo

El pro de este enfoque es que todo/la mayoría de los códigos de manejo de errores están en el nivel superior de su programa, y ​​todas las funciones en la cadena de llamadas no tienen que preocuparse ni un poquito sobre esto, todo lo que hacen es lanzar una excepción cuando lo deseen.

Cuestiones relacionadas