Ver Mensaje Individual
  #2 (permalink)  
Antiguo 19/11/2015, 08:42
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 3 meses
Puntos: 204
Respuesta: Usos del try en lugar de if

try-catch sirve para la gestión de excepciones. Las excepciones, en el caso de usarlas, únicamente deberían usarse para indicar situaciones anómalas, como por ejemplo que se ha perdido la conexión con la base de datos o que ha habido un problema al reservar memoria para un proceso.

La gracia de usar excepciones es que proporcionas a la aplicación un sistema homogéneo de gestión de errores capaz de proporcionar en tiempo de ejecución mucha más información que un simple return (como en C). La pega es que la gestión de excepciones exige código adicional en las funciones, además de que puedes provocar errores nuevos si no tienes en cuenta las exepciones... como fugas de memoria:

Código C++:
Ver original
  1. int* func()
  2. {
  3.   int* toReturn = new int[10];
  4.   throw "Error";
  5.  
  6.   // Este return no se ejecuta nunca pero la memoria sí que se ha reservado
  7.   return toReturn;
  8. }

El uso de excepciones se puede retorcer hasta el extremo de que podrías usarlas como sustituto del return... pero es desaconsejable por tres razones básicas:

  • no están pensadas para eso
  • Se va a tardar algo más de tiempo en entender el funcionamiento del código
  • El tiempo de ejecución es mayor


Código C++:
Ver original
  1. void suma(int a, int b)
  2. {
  3.   throw a+b;
  4. }
  5.  
  6. int main()
  7. {
  8.   try
  9.   {suma(4,3);}
  10.  
  11.   catch( int resultado )
  12.   { std::cout << "4 + 3 = " << resultado << std::end; }
  13. }

Así que no, try-catch no es un sustituto natural de if o de switch. La primera estructura sirve para la gestión de excepciones y las dos últimas para el control del flujo del programa. Son elementos diferentes con responsabilidades totalmente distintas.

--------------------
EDITO:

¿Qué pueden proporcionar las excepciones que no se pueda conseguir con otras estructuras? Dependiendo de cómo estructures tus excepciones, varias cosas:
  • Claridad en el diseño
  • Mucha información sobre la excepción sin necesidad de depurar
  • otros


Por ejemplo:

Código C++:
Ver original
  1. #include <iostream>
  2. #include <string>
  3.  
  4. class CustomException
  5. {
  6.   public:
  7.     CustomException(
  8.         const std::string& what,
  9.         const std::string& where,
  10.         int line)
  11.       : _what(what),_where(where),_line(line),_nested(0)
  12.     {
  13.     }
  14.  
  15.     CustomException(
  16.         const std::string& what,
  17.         const std::string& where,
  18.         int line,
  19.         const CustomException& nested)
  20.       : _what(what),_where(where),_line(line),_nested(new CustomException(nested))
  21.     {
  22.     }
  23.  
  24.     CustomException(const CustomException& other)
  25.       : _what(other._what),_where(other._where),_line(other._line),_nested(0)
  26.     {
  27.       if( other._nested)
  28.         _nested = new CustomException(*other._nested);
  29.     }
  30.  
  31.     ~CustomException()
  32.     { delete _nested; }
  33.  
  34.     std::string What() const
  35.     {return _what; }
  36.  
  37.     std::string Where() const
  38.     { return _where; }
  39.  
  40.     int Line() const
  41.     { return _line; }
  42.  
  43.     std::string ToString() const
  44.     {
  45.       std::string toReturn = _what + " in " + _where + ": " + std::to_string(_line) + "\n";
  46.       CustomException* ptr = _nested;
  47.       if( ptr )
  48.         toReturn += "Stack:\n";
  49.  
  50.       while( ptr )
  51.       {
  52.         toReturn += "\t" + ptr->Where() + ":" + std::to_string(ptr->_line) + " - " + ptr->What() + "\n";
  53.         ptr = ptr->_nested;
  54.       }
  55.  
  56.       return toReturn;
  57.     }
  58.  
  59.   private:
  60.     std::string _what;
  61.     std::string _where;
  62.     int _line;
  63.     CustomException* _nested;
  64. };
  65.  
  66. void func3()
  67. {
  68.   throw CustomException("Error X",__FUNCTION__,__LINE__);
  69. }
  70.  
  71. void func2()
  72. {
  73.   try
  74.   {
  75.     func3();
  76.   }
  77.  
  78.   catch( const CustomException& exc )
  79.   {
  80.     throw CustomException("Error raro",__FUNCTION__,__LINE__, exc);
  81.   }
  82. }
  83.  
  84. void func()
  85. {
  86.   try
  87.   {
  88.     func2();
  89.   }
  90.  
  91.   catch( const CustomException& exc )
  92.   {
  93.     throw CustomException("Error muy raro",__FUNCTION__,__LINE__,exc);
  94.   }
  95. }
  96.  
  97. int main()
  98. {
  99.   try
  100.   {
  101.     func();
  102.   }
  103.  
  104.   catch(const CustomException& exc)
  105.   {
  106.     std::cout << exc.ToString() << std::endl;
  107.   }
  108. }

Hacer esto con control de flujo requeriría bastante más esfuerzo y el resultado sería menos elegante.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.

Última edición por eferion; 19/11/2015 a las 09:06