Wollte ADD zu den anderen Antworten hier eine zusätzliche Note beschrieben, im Fall von benutzerdefinierten Ausnahmen .
std::exception
Wenn Sie eine eigene benutzerdefinierte Ausnahme erstellen, die sich aus dem Abfangen "aller möglichen" Ausnahmetypen ergibt , sollten Sie die catch
Klauseln immer mit dem "am meisten abgeleiteten" Ausnahmetyp beginnen, der möglicherweise abgefangen wird. Siehe das Beispiel (was NICHT zu tun ist):
#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;
}
HINWEIS:
0) Die richtige Reihenfolge sollte umgekehrt sein, dh zuerst Sie catch (const MyException& e)
, gefolgt von catch (const std::exception& e)
.
1) Wie Sie sehen, wird beim Ausführen des Programms wie es ist die erste catch-Klausel ausgeführt (was wahrscheinlich das ist, was Sie ursprünglich gar nicht wollten).
2) Obwohl der in der ersten catch-Klausel abgefangene Typ vom Typ ist std::exception
, wird die "richtige" Version von what()
aufgerufen - weil er als Referenz abgefangen wird (ändern Sie mindestens den std::exception
Typ des abgefangenen Arguments so , dass er nach Wert ist - und Sie werden das erleben "Object Slicing" -Phänomene in Aktion).
3) Für den Fall, dass der "Code aufgrund der Tatsache, dass eine XXX-Ausnahme ausgelöst wurde ..." wichtige Dinge in Bezug auf den Ausnahmetyp tut, liegt hier ein Fehlverhalten Ihres Codes vor.
4) Dies ist auch relevant, wenn die gefangenen Objekte "normale" Objekte waren wie: class Base{};
und class Derived : public Base {}
...
5) Unter g++ 7.3.0
Ubuntu 18.04.1 wird eine Warnung ausgegeben, die auf das erwähnte Problem hinweist:
In der Funktion 'void illustrDerivedExceptionCatch ()': item12Linux.cpp: 48: 2: Warnung: Ausnahme vom Typ 'MyException' wird abgefangen catch (const MyException & e) ^ ~~~~
item12Linux.cpp: 43: 2: Warnung: vom früheren Handler für 'std :: exception'
catch (const exception & e) ^ ~~~~
Auch hier möchte ich sagen, dass diese Antwort nur ist ADD beschrieben hier zu den anderen Antworten (dachte ich , dieser Punkt ist erwähnenswert, doch konnte es nicht innerhalb eines Kommentars zeigen).