Smart Pointer und Exception-Behandlung

8

Ich habe über das Internet und diesen Thread nach einem kompletten gesucht Antwort auf diese Situation Ich bin konfrontiert. Ich habe gelesen, dass das Werfen klug ist Zeiger auf Objekte sind nicht sehr schlau. Ich will nur verstehen warum ist das passiert. Ich werde die Situation erklären. Stellen wir uns das vor einfache Hierarchie:

%Vor%

Und lassen Sie uns diesen Testcode überprüfen:

%Vor%

Alles wird kompiliert, aber in der Laufzeit wird der zweite try-catch nicht sein hingerichtet. Kann mir jemand erklären warum? Besonders wenn Codezeilen wie das funktioniert in der Laufzeit einwandfrei.

%Vor%

Ich verstehe, dass das Problem darin besteht, dass SPFooInherited nicht von SPFoo erbt (obwohl FooInherited von Foo erbt), aber es würde gerne wissen, was der Compiler / RTE anders macht als das Funktionsaufrufbeispiel, wenn eine Ausnahme abgefangen wird die Situation nicht lösen zu können. Liegt es daran, dass der Parameter catch nicht mit einem Parameter für den Funktionsaufruf übereinstimmt? Warum Foo & amp; funktioniert und SPFoo nicht?

Vielen Dank im Voraus.

Grüße, Iker.

    
Iker Jamardo 05.09.2011, 14:17
quelle

2 Antworten

13

Wie Sie in Ihrer Frage gesagt haben, ist SPFooInherited keine Unterklasse von SPFoo . Dies bedeutet, dass catch(SPFoo const&) keine Instanzen von SPFooInherited abfängt. Auf der anderen Seite wird FooInherited von Foo geerbt, und so wird catch(Foo const&) Instanzen von FooInherited fangen.

Um dies zu verstehen, benötigen Sie kein spezielles Verständnis des Compilers oder der Laufzeitumgebung. Es ist einfach ein Teil der Sprache.

Der Grund für den Aufruf der Funktion ist, dass tr1::shared_ptr einen nicht-expliziten Konstruktor hat, der eine implizite Konvertierung an Funktionsaufruf-Sites ermöglicht.

Das heißt: tr1::shared_ptr hat den folgenden Konstruktor:

%Vor%

Dies ermöglicht, dass shared_ptr aus einem anderen gemeinsam genutzten Zeigertyp erstellt wird. Die Implementierung dieses Konstruktors basiert auf der impliziten Konvertierung von FooInherited* nach Foo* , um den Zeiger tatsächlich in SPFooInherited in SPFoo zu speichern. Wenn diese implizite Konvertierung nicht vorhanden ist, wird der Code nicht kompiliert, und daher werden unsafe Konvertierungen zwischen shared_ptr s zu nicht verwandten Typen nicht auftreten.

Der grundlegende Unterschied zwischen dem Funktionsaufruf und dem Catch besteht darin, dass implizite Konvertierungen bei der Initialisierung von Funktionsargumenten auftreten, ein Catch jedoch nur einem einzelnen Typ entsprechen kann ( FooInherited ist-a Foo , damit er übereinstimmt ).

    
Mankarse 05.09.2011 14:23
quelle
3

Weil SPFoo keine Unterklasse von SPFooInherited ist. catch Blöcke fangen nur Objekte ein, die sich in ihrer Fangliste befinden, oder eine öffentliche Kindklasse von dem, was sich in ihrer Fangliste befindet. FooInherited macht inhertit von Foo , so dass du mit Foo auch FooInherited fangen kannst. SPFoo und SPFooInherited sind völlig verschiedene und nicht verwandte Klassen.

    
Seth Carnegie 05.09.2011 14:24
quelle

Tags und Links