Queria ADD para as outras respostas aqui descritas uma nota adicional, no caso de exceções personalizadas .
No caso em que você cria sua própria exceção personalizada, que deriva de std::exception
, quando você captura os tipos de exceções "todos os possíveis", sempre deve iniciar as catch
cláusulas com o tipo de exceção "mais derivado" que pode ser capturado. Veja o exemplo (do que NÃO fazer):
#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) A ordem correta deve ser vice-versa, ou seja, primeiro você catch (const MyException& e)
é seguido por catch (const std::exception& e)
.
1) Como você pode ver, quando você executa o programa como está, a primeira cláusula catch será executada (o que provavelmente é o que você NÃO queria em primeiro lugar).
2) Embora o tipo capturado na primeira cláusula catch seja do tipo std::exception
, a versão "adequada" what()
será chamada - porque é capturada por referência (altere pelo menos o std::exception
tipo de argumento capturado por valor - e você experimentará o fenômenos de "corte de objetos" em ação).
3) Caso o "algum código devido ao fato de a exceção XXX ter sido lançada ..." faça coisas importantes COM RESPEITO ao tipo de exceção, há um mau comportamento do seu código aqui.
4) Isso também é relevante se os objetos capturados forem objetos "normais" como: class Base{};
e class Derived : public Base {}
...
5) g++ 7.3.0
no Ubuntu 18.04.1 produz um aviso que indica o problema mencionado:
Na função 'void illustrateDerivedExceptionCatch ()': item12Linux.cpp: 48: 2: warning: a exceção do tipo 'MyException' será capturada catch (const MyException & e) ^ ~~~~
item12Linux.cpp: 43: 2: warning: pelo manipulador anterior para a
captura 'std :: exception' (exceção const & e) ^ ~~~~
Mais uma vez , eu vou dizer, que esta resposta é apenas para ADD para as outras respostas aqui descritas (Eu pensei que este ponto vale a pena mencionar, ainda não poderia representá-lo dentro de um comentário).