2013-05-24 16 views
6

Ich bin C# Programmierer, aber jetzt möchte ich mehr in C++ zu bekommen.
Ich kenne die Grundlagen von C++, aber ich weiß nicht, wie man mit Fehlern umgeht.
Sollte ich eine Ausnahme werfen

Zum Beispiel: Ich schreibe eine Bibliothek. Ich erstelle einen Konstruktor, der eine Ganzzahl als Argument anfordert.
Wenn diese Ganzzahl größer als 50 ist, handelt es sich um einen Fehler. In C# würde ich eine ArgumentOutOfRange Ausnahme werfen, aber was soll ich in C++ tun?

+0

mögliche Duplikate von [Wie Fehler in Konstruktor in C++ umgehen?] (Http://stackoverflow.com/questions/4989807/how-to-handle-failure-in-constructor-in -c) –

+0

@stefan, in C++ benutzt man keine Ausnahmen, um den Programmablauf zu steuern. wegfahren von Frage - es könnte eine gute Idee sein, eine Fabrik zu machen, die alle erforderlichen Kontrollen und vermeidet die Verwendung von Ausnahmen aus falschen Gründen – ShPavel

Antwort

21

In C# würde ich eine ArgumentOutOfRange Ausnahme werfen, aber was soll ich in C++ tun?

Zuerst sollten Sie prüfen, ob das nicht eine Voraussetzung Ihre Funktion sein sollte, so dass die Verantwortung für die Überprüfung, ob der Wert im Bereich der Anrufer ist.

Wenn Sie sich für diese Option entscheiden, wäre das Aufrufen der Funktion mit einem Wert außerhalb des Bereichs ein undefiniertes Verhalten, und innerhalb der Funktion könnten Sie einfach eine Debug-Assertion haben, um mögliche Fehler zu erkennen irgendeine Ausnahme werfen.

Wenn Sie entscheiden, dass die Funktion einen breiten Vertrag haben sollte, und auf eine eindeutige Weise reagieren und eine Ausnahme auslösen, wenn das Argument außerhalb des zulässigen Bereichs liegt, können Sie eine std::out_of_range Ausnahme auslösen.

Zum Beispiel: Ich schreibe ein libary [...]

Wenn Sie eine Bibliothek schreiben, was bedeutet, dass Sie nicht die genauen Anforderungen Ihrer Kunden in Bezug auf Leistung und Robustheit wissen Sie können in Betracht ziehen, zwei solche Funktionen bereitzustellen - eine mit einem breiten Vertrag, der Ausnahmen auslöst, und eine mit einem engen Vertrag, der davon ausgeht, dass der Client sinnvolle Eingaben liefert.

Auf diese Weise kann der Benutzer Ihrer Bibliothek basierend auf ihren Anwendungsfällen entscheiden, ob es in Ordnung ist, den Aufwand für die Überprüfung der Korrektheit der Eingabe jedes Mal zu zahlen, wenn Ihre Funktion aufgerufen wird.

Dies ist zum Beispiel der von der C++ Standard Library angenommene Strategie für std::vector, die für den Zugriff auf Elemente der Kollektion basiert auf dem Index (diese Funktion Verhalten hat nicht definiert ein nicht-Wurf operator[] mit einem schmalen Vertrag sieht vor, wenn die Index ist außerhalb des gültigen Bereichs) und eine Memberfunktion at(), die die Indexprüfung durchführt und eine Ausnahme auslöst, wenn der Index außerhalb des gültigen Bereichs liegt.

+4

Guter Beitrag rundherum. +1 Assertion (pre/post-Bedingungen), std :: vector-Beispiele und Optionen. – Freddy

+0

@Freddy: Schön, dass Sie es hilfreich fanden –

+1

Ihre lange und wahrscheinlich richtige Antwort über Ausnahmen kann OP auf die falsche Seite der Gewalt führen. Kerrek SB nächste Antwort sollte in dieser Situation auch berücksichtigt werden, um Kommentare zu vermeiden, wie von @stefan zur ursprünglichen Frage – ShPavel

3

Das gleiche wie in C#: eine Ausnahme auslösen. Nur so kann verhindert werden, dass ein Objekt erstellt wird.

std::invalid_argument ist eine gute Standard-Wahl in Bezug auf was zu werfen.

4

Es hängt davon ab, ob eine Ganzzahl größer als 50 möglicherweise als Teil des normalen Programmablaufs an den Konstruktor übergeben werden kann, oder ob dies eine Ausnahmebedingung ist. Aber im Allgemeinen besteht die einzige Möglichkeit, die Objektkonstruktion zu scheitern, darin, eine Ausnahme auszulösen.

Ihr Benutzercode könnte wie folgt aussehen:

int n = parse_user_input() 

if (n < 50) 
{ 
    Foo x(n); 
    x.do_cool_stuff(); 
} 
else 
{ 
    // report user error 
} 

Das heißt, Sie eigentlich keine Ausnahmen für den normalen Kontrollfluss verwenden. Mit dieser Art von Codemuster wäre es vollkommen in Ordnung, Foo::Foo(int) eine Ausnahme auszulösen, wenn das Argument außerhalb des Bereichs liegen würde.

Sie können nützliche Standardausnahmeklassen in <stdexcept> finden.

0

Aus dem C++ FAQ: [17.8] How can I handle a constructor that fails?

Auszug:

eine Ausnahme werfen.

Konstruktoren haben keinen Rückgabetyp, daher ist es nicht möglich, Rückkehrcodes zu verwenden. Der beste Weg, um einen Konstruktorfehler zu signalisieren, ist daher , um eine Ausnahme auszulösen. Wenn Sie nicht die Möglichkeit haben, Ausnahmen zu verwenden, ist die "am wenigsten schlechte" Problemumgehung, das Objekt in einen "Zombie" -Zustand zu versetzen, indem ein internes Statusbit gesetzt wird, so dass das Objekt ist obwohl es technisch noch am Leben ist.

So std::invalid_argument oder std::out_of_range werfen würde für Ihre Situation durchaus akzeptabel sein. Sie könnten auch eine benutzerdefinierte Ausnahme werfen, wenn das in Ihrer Situation vorteilhaft wäre. In der C++ - FAQ finden Sie unter: [17.12] What should I throw?

Verwandte Themen