Liegt es nur am Stacktrace (was in C++ sowieso kein Standard ist wie in C# oder Java)?
(Wenn es einen Unterschied macht, verwende ich MSVS 2008.)
throw ex; // out of apartment
– Fredoverflow
14. August ’12 um 11:27
@sehe, mein Fehler, ich habe den Punkt total verfehlt.
– Charles D Pantoga
9. Oktober ’13 um 2:01
Naveen
throw; wirft dasselbe Ausnahmeobjekt erneut aus, das es währenddessen abgefangen hat throw ex; löst eine neue Ausnahme aus. Es macht keinen Unterschied, außer aus Performancegründen, ein neues Ausnahmeobjekt zu erstellen. Wenn Sie eine Ausnahmehierarchie haben, von der einige andere Ausnahmeklassen abgeleitet sind MyException -Klasse und beim Auslösen einer Ausnahme haben Sie Folgendes getan: throw DerivedClassException; es kann von der gefangen werden catch(MyException&). Wenn Sie nun dieses abgefangene Ausnahmeobjekt ändern und mit erneut auslösen throw; der Typ des Ausnahmeobjekts wird weiterhin sein DerivedClassException. Wenn Sie tun throw Ex; das Objekt-Slicing findet statt und die neu ausgelöste Ausnahme hat den Typ MyException.
das kommt darauf an was Ex ist. Im Beispiel ist es das gleiche Objekt, das per Referenz abgefangen wird (was der Standardweg ist).
– philsquared
2. Dezember ’09 um 16:31
@Naveen, Objekt-Slicing findet nicht statt, wenn Sie per Referenz gefangen haben. Wenn Sie nach Wert fangen, wäre das Schneiden bereits erfolgt, obwohl zu diesem Zeitpunkt throw; würde Sie retten, weil es die ursprüngliche Ausnahme erneut auslöst)
– philsquared
2. Dezember ’09 um 16:35
@Phil: nein, lies 15.1/3 und 15.1/6. Selbst wenn ex ist eine Referenz, throw ex; wirft (notwendigerweise) den Referanden nicht, es initialisiert ein temporäres Objekt mit dem Referanden. Das Provisorium kann aufgehoben werden oder nicht. throw;, andererseits wird angegeben, um das vorhandene temporäre wiederzuverwenden.
– Steve Jessop
2. Dezember ’09 um 16:42
@Phil: Effektiveres C++-Element 12 überprüft, Objekt-Slicing tritt auf. Meine Antwort auf die ursprüngliche Antwort zurückgesetzt.
– Naveen
2. Dez. 09 um 16:50
@Managu – Werfen / Fangen per Zeiger funktioniert wie erwartet. Der Unterschied besteht darin, dass der Wert eines Zeigers die Adresse ist, aber der Wert einer Referenz das ist, worauf sie verweist (auch wenn sie durch Zeiger unter der Haube implementiert wird).
– philsquared
2. Dezember ’09 um 16:51
kurzlebig
[C++ FAQ Lite § 17.9] Was macht throw; (ausnahmslos Objekt nach dem throw Stichwort) bedeuten? Wo würde ich es verwenden?
Möglicherweise sehen Sie Code, der in etwa so aussieht:
In diesem Beispiel ist die Anweisung throw; bedeutet “die aktuelle Ausnahme erneut auslösen.” Hier hat eine Funktion eine Ausnahme abgefangen (durch einen nicht konstanten Verweis), die Ausnahme geändert (indem sie Informationen hinzugefügt hat) und dann die Ausnahme erneut ausgelöst. Dieses Idiom kann verwendet werden, um eine einfache Form von Stack-Trace zu implementieren, indem Sie den wichtigen Funktionen Ihres Programms entsprechende Catch-Klauseln hinzufügen.
Eine andere Redewendung ist der “Exception Dispatcher”:
Objekte, die geworfen werden, müssen einen öffentlich zugänglichen Kopierkonstruktor haben. Der Compiler darf Code generieren, der das geworfene Objekt beliebig oft kopiert, einschließlich null. Aber selbst wenn der Compiler das geworfene Objekt nie tatsächlich kopiert, muss er sicherstellen, dass der Kopierkonstruktor der Ausnahmeklasse vorhanden und zugänglich ist.
(bearbeitet, um mehr Klarheit darüber zu erhalten, was ich für offensichtlich hielt …)
catch(MyException& ex) { throw ex; } darf kopieren ex, mit allen damit verbundenen Problemen; catch(MyException& ex) { throw; } nicht dürfen.
Sicher, aber da ich im obigen Code wählen kann, ob ich das eine oder andere tun möchte, was ist der Unterschied?
– Joshua Fox
2. Dez. 09 um 16:40
Tolle Antwort, ich füge den Kommentar hinzu, dass wir in unserem Code eine Beschleunigung festgestellt haben, indem wir einen großen Block des Ausnahmefangs in seine eigene Funktion verschoben haben. Die Beschleunigung war darauf zurückzuführen, dass die Funktionen verkleinert wurden, indem die Catch-Blöcke in eine Funktion gesteckt wurden.
– Chollida
2. Dezember ’09 um 16:41
Mir war das Idiom “Ausnahme-Dispatcher” noch nie aufgefallen. Interessant.
– Greg D
2. Dez. 09 um 17:18
Wenn Sie eine Ausnahmehierarchie haben, throw ex kann deine Ausnahme schneiden, während throw Gewohnheit. Beispielsweise:
#include <iostream>
#include <string>
using namespace std;
struct base
{
virtual string who() {return "base";}
};
struct derived : public base
{
string who() {return "derived";}
};
int main() {
try {
try {
throw derived(); // throws a 'derived'
}
catch (base& ex)
{
throw ex; // slices 'derived' object to be a 'base' object
}
}
catch (base& ex)
{
cout<<ex.who()<<endl; // prints 'base'
}
}
Veränderung throw ex nur throw, und Sie erhalten eine Ausgabe von derived, was Sie wahrscheinlich erwartet haben.
Danke. Das ist überraschend. Ich würde nicht glauben, dass Slicing bei der Behandlung eines Objekts als Referenz auftreten kann.
– Joshua Fox
2. Dez. 09 um 16:44
philsquared
Du kannst den … benutzen throw; bilden mit catch(...) (das ist die einzige Möglichkeit zum erneuten Werfen, wenn Sie mit catch(…) erwischt wurden).
throw ex; // out of apartment
– Fredoverflow
14. August ’12 um 11:27
@sehe, mein Fehler, ich habe den Punkt total verfehlt.
– Charles D Pantoga
9. Oktober ’13 um 2:01