Quería AGREGAR a las otras respuestas descritas aquí una nota adicional, en el caso de excepciones personalizadas .
En el caso de que cree su propia excepción personalizada, que se deriva de std::exception
, cuando captura "todos los tipos de excepciones posibles", siempre debe comenzar las catch
cláusulas con el tipo de excepción "más derivado" que se puede detectar. Vea el ejemplo (de lo que NO debe hacer):
#include <iostream>
#include <string>
using namespace std;
class MyException : public exception
{
public:
MyException(const string& msg) : m_msg(msg)
{
cout << "MyException::MyException - set m_msg to:" << m_msg << endl;
}
~MyException()
{
cout << "MyException::~MyException" << endl;
}
virtual const char* what() const throw ()
{
cout << "MyException - what" << endl;
return m_msg.c_str();
}
const string m_msg;
};
void throwDerivedException()
{
cout << "throwDerivedException - thrown a derived exception" << endl;
string execptionMessage("MyException thrown");
throw (MyException(execptionMessage));
}
void illustrateDerivedExceptionCatch()
{
cout << "illustrateDerivedExceptionsCatch - start" << endl;
try
{
throwDerivedException();
}
catch (const exception& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an std::exception, e.what:" << e.what() << endl;
// some additional code due to the fact that std::exception was thrown...
}
catch(const MyException& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an MyException, e.what::" << e.what() << endl;
// some additional code due to the fact that MyException was thrown...
}
cout << "illustrateDerivedExceptionsCatch - end" << endl;
}
int main(int argc, char** argv)
{
cout << "main - start" << endl;
illustrateDerivedExceptionCatch();
cout << "main - end" << endl;
return 0;
}
NOTA:
0) El orden correcto debe ser al revés, es decir, primero usted, catch (const MyException& e)
seguido de catch (const std::exception& e)
.
1) Como puede ver, cuando ejecuta el programa tal como está, se ejecutará la primera cláusula catch (que probablemente es lo que NO quería en primer lugar).
2) Aunque el tipo capturado en la primera cláusula catch es de tipo std::exception
, what()
se llamará a la versión "adecuada" , porque se captura por referencia (cambie al menos el std::exception
tipo de argumento capturado por valor) y experimentará el fenómenos de "corte de objetos" en acción).
3) En caso de que "algún código debido al hecho de que se lanzó la excepción XXX ..." hace cosas importantes CON RESPECTO al tipo de excepción, hay un mal comportamiento de su código aquí.
4) Esto también es relevante si los objetos capturados eran objetos "normales" como: class Base{};
y class Derived : public Base {}
...
5) g++ 7.3.0
en Ubuntu 18.04.1 produce una advertencia que indica el problema mencionado:
En la función 'void illustrateDerivedExceptionCatch ()': item12Linux.cpp: 48: 2: advertencia: se capturará la excepción del tipo 'MyException' (const MyException & e) ^ ~~~~
item12Linux.cpp: 43: 2: advertencia: por el controlador anterior para 'std :: excepción'
catch (const except & e) ^ ~~~~
Una vez más , diré que esta respuesta es solo para AGREGAR a las otras respuestas descritas aquí (pensé que vale la pena mencionar este punto, pero no pude describirlo en un comentario).