Wie erhalte ich eine Konstruktorausnahme?

8

Ich habe eine C ++ - Klasse, die bei einem Fehler eine Ausnahme vom Konstruktor auslöst. Wie kann ich eine lokale Instanz dieser Klasse zuweisen (ohne new zu verwenden) und alle möglichen Ausnahmen behandeln, während der try Blockbereich so klein wie möglich gehalten wird?

Im Wesentlichen suche ich nach dem C ++ - Äquivalent des folgenden Java-Idioms:

%Vor%

Ich möchte keine Ausnahmen von x.doSomething() , nur den Konstruktor abfangen.

Ich nehme an, dass ich nach einer Möglichkeit suche, die Deklaration und die Initialisierung von x zu trennen.

Ist es möglich, dies ohne Verwendung von Heap-Zuweisungen und -Zeigern zu erreichen?

    
Andrew Sun 02.08.2016, 08:26
quelle

7 Antworten

11

Sie können std :: optional aus C ++ 17:

verwenden %Vor%     
songyuanyao 02.08.2016, 08:45
quelle
5

Dieses Java-Idiom kann nicht gut in C ++ übersetzt werden, da Bar x; Standardkonstruktor erfordert, selbst wenn Ihr realer Konstruktor die Übergabe von Argumenten erfordert.

Ich würde empfehlen, die Sprache in diesem Maße zu bekämpfen - die Erweiterung des Blocks try ist ausreichend - aber wenn Sie wirklich möchten, können Sie eine Funktion verwenden und verlassen Sie sich auf Rückgabewertoptimierung , um eine Wertkopie zu vermeiden:

%Vor%

Aber wirklich, Sie könnten eine spezielle Ausnahme auf die Konstruktion werfen, so dass Sie diese Funktion vollständig umgehen würden.

    
Bathsheba 02.08.2016 08:34
quelle
5

Ja, es ist möglich, wenn Sie den gesamten Code in die try -Klausel einfügen, z. B. mit function try block (um unnötiges Verschachteln und Scoping zu vermeiden):

%Vor%

Oder rufen Sie in der try -Klausel eine andere Funktion auf, die die eigentliche Arbeit erledigt:

%Vor%

Beachten Sie, dass es oft keine gute Idee ist, Exceptions in einen Konstruktor zu schreiben, da dies die Konstruktion des Objekts stoppt und dessen Destruktor nicht aufgerufen wird.

Wie von Holt angemerkt, werden dadurch auch Ausnahmen vom Aufruf doSomething abgefangen. Es gibt zwei Möglichkeiten, das zu lösen:

  1. Der einfache und standardmäßige Weg: Verwenden Sie Zeiger .

  2. Verwenden Sie zweistufige Konstruktion: Verwenden Sie einen Standardkonstruktor, der keine Ausnahmen auslösen kann, und rufen Sie dann eine spezielle "Konstrukt" -Funktion auf, die Ausnahmen auslösen kann.

Der zweite Weg war üblich, bevor C ++ standardisiert wurde, und wurde weitgehend im Code des Symbian-Systems verwendet. Es ist nicht mehr üblich, da die Verwendung von Zeigern viel einfacher und einfacher ist, besonders heute mit guten Smartpointern. Ich empfehle wirklich nicht den zweiten Weg im modernen C ++.

Der einfachste Weg besteht natürlich darin, sicherzustellen, dass der Konstruktor keine Exceptions werfen kann, oder wenn irgendetwas geworfen wird, dann sind sie von der Art, dass das Programm nicht fortgesetzt werden kann und das Programm beendet werden muss. Wie in den Kommentaren zu Ihrer Frage angemerkt, sind Ausnahmen in C ++ teuer, und dann haben wir auch das Problem der abgebrochenen Konstruktion, und alle Ausnahmen in C ++ sollten nur in Ausnahmefällen verwendet werden. C ++ ist kein Java, Sie sollten es nicht als solches behandeln, selbst wenn es ähnliche Konstrukte in beiden Sprachen gibt.

Wenn Sie immer noch Exceptions vom Konstruktor abwerfen wollen, gibt es tatsächlich eine dritte Möglichkeit, nur diese einzufangen: Verwenden Sie eines der Codebeispiele oben und werfen Sie nur bestimmte Ausnahmen, die doSomething niemals werfen und dann abfangen kann nur bestimmte Konstruktoren.

    
Some programmer dude 02.08.2016 08:33
quelle
2

Wenn Sie Heap-Zuordnungen vermeiden möchten, können Sie normalerweise die Deklaration einer lokalen Variablen nicht von ihrer Definition trennen. Wenn Sie also alles in einer einzigen Funktion kombinieren möchten, müssen Sie den gesamten Bereich von x mit try/catch block:

umgeben %Vor%     
Smeeheey 02.08.2016 08:32
quelle
2

Nein. In Ihrem Java-Beispiel müssen Sie zwischen diesen beiden Möglichkeiten wählen:

Ohne Zeiger:

%Vor%

Mit Zeigern:

%Vor%

Oder verwaltete Zeiger verwenden:

%Vor%     
wasthishelpful 02.08.2016 08:34
quelle
2

Sie müssen zwischen den Varianten von

wählen %Vor%

oder

%Vor%     
Jarod42 02.08.2016 08:32
quelle
1

In der überarbeiteten Frage fügt das OP die Anforderung hinzu, dass

  

" Ich möchte keine Ausnahmen von x.doSomething() abfangen, nur den Konstruktor [der lokalen Variablen].

Eine einfache Möglichkeit, den Java-Code zu übersetzen

%Vor%

... bis C ++, dann wird eine Optional_ Klasse verwendet (wie Barton-Nackmann Fallible , boost::optional oder C ++ 17 std::optional )

%Vor%

Eine gute Alternative ist, diesen Code wie folgt umzuformen:

%Vor%

Wenn Ihnen die obigen Ansätze nicht gefallen, können Sie immer eine dynamisch zugewiesene Bar -Instanz wählen, z. Verwenden von std::unique_ptr für die garantierte Bereinigung, die jedoch den allgemeinen Aufwand für eine dynamische Zuordnung hat. In Java wird fast jedes Objekt dynamisch zugewiesen, so dass dies kein ernsthafter Nachteil zu sein scheint. Aber in C ++ sind die meisten Objekte superschnell stack-allocated, so dass eine dynamische Zuweisung eine sehr langsame Operation im Vergleich zu normalen Operationen ist, so dass die mögliche konzeptionelle Einfachheit der dynamischen Zuweisung dagegen gewichtet werden muss.

    
Cheers and hth. - Alf 02.08.2016 08:49
quelle