- Ausnahmeverkettung: Ich möchte das Konzept der „Ausnahmeübersetzung“ implementieren, wenn auf höheren Ebenen abgefangene Ausnahmen die Ausnahmen auf niedrigerer Ebene umschließen und „übersetzen“, wobei diese Ausnahmen auf niedrigerer Ebene auch irgendwie erhalten bleiben (in diesem Fall im InnerException-Member). Zu diesem Zweck sollte es einen Mechanismus geben, um innere Ausnahmen zusammen mit jeder auf der oberen Ebene ausgelösten Ausnahme zu speichern. Das InnerException-Mitglied stellt dies in der folgenden Implementierung bereit.
- Ausnahmevererbung: Es sollte beispielsweise möglich sein, IoException von Exception und SerialPortException von IoException abzuleiten. Obwohl dies trivial erscheint, sollte es möglich sein, die Art der abgefangenen Ausnahmen dynamisch zu identifizieren (z. B. für Protokollierungszwecke oder zur Anzeige für den Benutzer), vorzugsweise ohne den Mehraufwand von RTTI und Typ-ID.
Code: Select all
try
{
try
{
try
{
throw ThirdException(L"this should be ThirdException");
}
catch(Exception &ex)
{
throw SubException(L"this should be SubException", ex);
}
}
catch(Exception &ex)
{
throw SubException(L"this should be SubException again", ex);
}
}
catch(Exception &ex)
{
throw Exception(L"and this should be Exception", ex);
}

Ich habe mir also die folgende Implementierung ausgedacht weit:
Kleiner Hinweis: CString ist eine Microsoft-spezifische String-Klasse (nur für Leute, die mit Visual C++ nicht vertraut sind).
Code: Select all
class Exception
{
protected:
Exception(const Exception&) {};
Exception& operator= (const Exception&) {};
public:
Exception(const CString &message) : InnerException(0), Message(message) {}
Exception(const CString &message, const Exception &innerException) : InnerException(innerException.Clone()), Message(message) {}
virtual CString GetExceptionName() const { return L"Exception"; }
virtual Exception *Clone() const
{
Exception *ex = new Exception(this->Message);
ex->InnerException = this->InnerException ? this->InnerException->Clone() : 0;
return ex;
}
public:
virtual ~Exception() { if (InnerException) delete InnerException; }
CString Message;
const Exception *InnerException;
};
Jetzt erledigt das den Job. Aber ... diese Lösung gefällt mir aus einem bestimmten Grund nicht: der Menge an Codierung, die für jede abgeleitete Klasse erforderlich ist. Bedenken Sie, dass ich die SubException-Klasse ableiten muss, die absolut keine Ergänzungen zur Basisklassenfunktionalität bereitstellt. Sie stellt lediglich den benutzerdefinierten Namen („SubException“, der möglicherweise „IoException“, „ProjectException“ usw. sein kann) bereit, um sie für ihr Verwendungsszenario zu unterscheiden. Ich muss für jede dieser Ausnahmeklassen fast die gleiche Menge Code bereitstellen. Hier ist es:
Code: Select all
class SubException : public Exception
{
protected:
SubException(const SubException& source) : Exception(source) {};
SubException& operator= (const SubException&) {};
public:
SubException(const CString &message) : Exception(message) {};
SubException(const CString &message, const Exception &innerException) : Exception(message, innerException) {};
virtual CString GetExceptionName() const { return L"SubException"; }
virtual Exception *Clone() const
{
SubException *ex = new SubException(this->Message);
ex->InnerException = this->InnerException ? this->InnerException->Clone() : 0;
return ex;
}
};
Code: Select all
InnerExceptionP.S.: Ich weiß, dass es in C++11 (auch in Boost) einige Mechanismen für diesen Zweck (Ausnahmeverkettung) mit einigen neuen Ausnahmeklassen gibt, aber ich interessiere mich hauptsächlich für benutzerdefinierte, „mit altem C++ kompatible“ Methoden. Aber es wäre darüber hinaus gut, wenn jemand Code in C++11 bereitstellen könnte, der dasselbe erreicht.
Mobile version