Frage

Gibt es eine gute Praxis zu dynamic_cast Fehlern im Zusammenhang Handhabung (außer es nicht verwenden, wenn Sie müssen nicht)? Ich frage mich, wie soll ich über NULL gehen und bad_cast es werfen kann. Soll ich überprüfen für beide? Und wenn ich bad_cast oder erkennen NULL fangen wahrscheinlich erholen kann ich sowieso nicht ... Denn jetzt bin ich mit assert zu überprüfen, ob dynamic_cast nicht NULL Wert zurückgegeben. Würden Sie diese Lösung auf einem Code-Review akzeptieren?

War es hilfreich?

Lösung

Wenn die dynamic_cast sollte Erfolg haben, wäre es eine gute Übung, anstatt zu verwenden boost::polymorphic_downcast, die ein wenig etwas geht:

assert(dynamic_cast<T*>(o) == static_cast<T*>(o));
return static_cast<T*>(o);

Auf diese Weise werden Sie Fehler in dem Debug-Build erfassen, während zur gleichen Zeit, um den Laufzeit-Overhead in einem Release-Build zu vermeiden.

Wenn Sie die Besetzung vermuten könnte fehlschlagen und Sie wollen es zu erfassen, verwenden dynamic_cast und Umwandlung in einen Referenztyp. Diese Umwandlung wird bad_cast im Fehlerfall werfen, und wird Ihr Programm aufnehmen. (Dies ist gut, wenn, wie Sie sagen, Sie sind sowieso nicht mehr erholen werden)

T& t = dynamic_cast<T&>(o);
t.func(); //< Use t here, no extra check required

Verwenden dynamic_cast auf einen Zeigertyp nur, wenn die 0-pointer Sinn im Kontext macht. Vielleicht möchten Sie es in einem if wie folgt verwenden:

if (T* t = dynamic_cast<T*>(o)) {
    t->func(); //< Use t here, it is valid
}
// consider having an else-clause

Mit dieser letzten Option müssen Sie sicherstellen, dass der Ausführungspfad Sinn macht, wenn die dynamic_cast 0 zurück.

Ihre Frage direkt zu beantworten: ich einen der beiden ersten Alternativen vorziehen würde ich gegeben habe, in dem Code eine explizite assert zu haben:)

Andere Tipps

bad_cast wird nur ausgelöst, wenn Referenzen Gießen

dynamic_cast< Derived & >(baseclass)

NULL wird zurückgegeben, wenn Casting Zeiger

dynamic_cast< Derived * >(&baseclass)

So gibt es nie eine Notwendigkeit, beide zu überprüfen.

Assert akzeptabel sein kann, aber das hängt stark vom Kontext ab, dann wieder, das stimmt für so ziemlich jedes assert ...

Ja und nein.

boost::polymorphic_downcast<> ist sicherlich eine gute Option Fehler dynamic_cast<> während der Debug-Phase zu behandeln. Allerdings ist es erwähnenswert, dass polymorphic_downcast<> zu erwähnen sollte nur verwendet werden, wenn es ist möglich, den polymorphen Typen bei der Kompilierung , da sonst die dynamic_cast<> sollte anstelle davon verwendet wird, übergeben prognostizieren.

jedoch eine Folge von:

if (T1* t1 = dynamic_cast<T1*>(o)) 
{ }
if (T2* t2 = dynamic_cast<T2*>(o)) 
{ }
if (T3* t3 = dynamic_cast<T3*>(o)) 
{ }

bezeichnet ein sehr schlechtes Design, das von Polymorphismus regeln sollte und virtuelle Funktionen .

Es hängt davon ab ...; -)

Wenn ich wirklich die dynamic_cast erwarte mir etwas Brauchbares, zum Beispiel zu geben, wenn ich und sonst niemand einen polymorphen Typen in einen Behälter mit Zeigern auf eine Basisklasse hinzugefügt, dann würde ich mit dem Referenzguss gehen und die std::bad_cast töten lassen meine Anwendung -. es sonst nicht viel, wirklich zu tun wäre,

Allerdings, wenn ich eine polymorphe Typ für einige Fähigkeit durch eine Schnittstelle ausgesetzt Abfrage, dass es nicht unbedingt zu implementieren hat, dann würde ich mit dem Zeiger Guss gehen und dann würde ein NULL kein Fehler sein ( es sei denn natürlich, erwartete ich die Fähigkeit, wirklich es sein - aber dann würde ich hatte für die Referenz Besetzung in erster Linie ...)

gegangen

Ich würde zustimmen, mit der ‚es hängt‘ Antwort, und auch „Graceful Degradation“ hinzufügen: nur weil ein gegossenes irgendwo versagt ist nicht Grund genug, die Anwendung scheitern zu lassen (und der Benutzer seine / ihre Arbeit verlieren, usw. .). Ich würde eine Kombination empfehlen von behauptet und defensiver Programmierung:

ptr = dynamic_cast<MyClass>(obj);
ASSERT(ptr);
if(ptr)
{
   // do stuff
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top