Wie kann eine Instanz der Basisklasse eine Instanz der abgeleiteten Klasse enthalten?

8

Ich bin seit zwei Jahren .NET-Programmierer (kann nicht sagen, dass ich Programmierer bin). Es gibt eine Frage, die ich seit Jahren nicht verstehen kann. So könnte eine Instanz der Basisklasse eine Instanz der abgeleiteten Klasse enthalten.

Angenommen wir haben zwei Klassen:

%Vor%

Wie konnte das passieren?

%Vor%

Ich meine, das Speichermodell von BaseClass hat keinen Platz für die neu hinzugefügte Eigenschaft c, also wie könnte es noch den Wert von propertyC enthalten?

Auf der anderen Seite, wie könnte das nicht passieren:

%Vor%

Ich dachte, das ist der richtige Weg, da das Speichermodell von DerivedClass alle Leerzeichen für die BaseClass und noch mehr hat. Aber das ist nicht wahr, warum?

Ich weiß, dass ich eine wirklich dumme Frage stelle, aber könnte mir jemand eine genauere Antwort geben? Es wäre besser aus der Perspektive des Speichers oder Compilers.

    
NextStep 10.11.2011, 02:30
quelle

5 Antworten

5

Weil (und dieses Konzept oft missverstanden wird) wird die Variable, die den Zeiger enthält, unabhängig vom tatsächlichen konkreten Typ des Objekts, auf das sie zeigt, eingegeben.

Also wenn du schreibst

%Vor%

Der Teil, der BaseClass obj angibt, erstellt eine neue Referenz Variable im Stack, die der Compiler versteht, um eine Referenz auf etwas zu halten, das von BaseClass stammt oder abgeleitet wird.

Der Teil, der = new DerivedClass () liest, erstellt tatsächlich ein neues Objekt vom Typ DerivedClass , speichert es auf dem Heap und speichert einen Zeiger auf dieses Objekt in der Speicherort, auf den obj zeigt. Das tatsächliche Objekt auf dem Heap ist ein DerivedClass ; Dies wird als konkreter Typ des Objekts bezeichnet.

Die Variable obj wird vom Typ BaseClass deklariert. Dies ist kein konkreter Typ , sondern nur ein Variablentyp , der den Compiler nur beschränkt, eine Adresse in die Variable zu speichern, die auf zeigt ein Objekt, das kein BaseClass ist oder das nicht vom Typ BaseClass abgeleitet ist.

Dies wird getan, um zu garantieren, dass alles, was Sie in die Variable obj eingeben, egal ob es sich um einen konkreten Typ von BaseClass oder DerivedClass handelt, alle Methoden, Eigenschaften und andere Member vom Typ% co_de haben %. Es teilt dem Compiler mit, dass alle Verwendungen der Variable BaseClass auf die Verwendung nur der Member der Klasse obj beschränkt werden sollten.

    
Charles Bretana 10.11.2011, 02:52
quelle
4

Da BaseClass ein Referenztyp ist, ist obj kein BaseClass -Objekt. Es ist eine Referenz für ein BaseClass -Objekt. Insbesondere ist dies ein Verweis auf den BaseClass -Teil von DerivedClass .

    
Raymond Chen 10.11.2011 02:39
quelle
2

Wenn Sie das sagen:

%Vor%

Sie sagen NICHT "Erstellen Sie einen Container, der dieses BaseClass-Objekt enthält, und fügen Sie dann dieses größere DerivedClass-Objekt ein".

Sie erstellen tatsächlich ein DerivedClass-Objekt und es wird in einem Speicherbereich erstellt, der für ein DerivedClass-Objekt ausreicht. Niemals verliert das .NET-Framework den Überblick über die Tatsache, dass dieses Ding speziell eine DerivedClass ist, noch hört es auf, es als solches zu behandeln.

Wenn Sie jedoch angeben, eine BaseClass-Objektvariable zu verwenden, erstellen Sie lediglich einen Verweis / Zeiger auf das Objekt, das bereits erstellt und zugewiesen und definiert wurde, und alles, und Ihr Zeiger ist nur ein wenig vager .

Es ist, als ob der Typ da drüben auf der anderen Seite des Raumes ein rothaariger irischer, leicht übergewichtiger Hühnerbauer mit schlechten Zähnen und charmanter Persönlichkeit namens Jimmy ist, aber Sie bezeichnen ihn nur als "diesen Kerl da drüben ". Die Tatsache, dass Sie ihn vage beschreiben, ändert nichts an dem, was er ist, oder an seinen Details, auch wenn Ihre vage Beschreibung genau ist.

    
Mike Mooney 10.11.2011 02:55
quelle
0

Antwort wurde wortwörtlich kopiert von dem, was ein anderer Benutzer, jk, in Stackofflow auf genau die gleiche Frage geschrieben hat.

  

Wenn ich dir sage, dass ich einen Hund habe, kannst du davon ausgehen, dass ich einen Hund habe.

     

Wenn ich dir sage, dass ich ein Haustier habe, weißt du nicht, ob dieses Tier ein Hund ist   könnte eine Katze oder vielleicht sogar eine Giraffe sein. Ohne etwas extra zu wissen   Informationen, die Sie nicht sicher annehmen können, habe ich einen Hund.

     

Ähnlich ist ein abgeleitetes Objekt ein Basisklassenobjekt (als ein Sub-Objekt   Klasse), auf die ein Basisklassenzeiger zeigen kann. aber eine Basis   Das Klassenobjekt ist kein abgeleitetes Klassenobjekt und kann daher keinem a zugewiesen werden   abgeleiteter Klassenzeiger.

     

(Das Knarren, das Sie jetzt hören werden, ist die Analogie, die sich ausdehnt)

     

Angenommen, Sie möchten mir jetzt ein Geschenk für mein Haustier kaufen.

     

Im ersten Szenario weißt du, dass es ein Hund ist, du kannst mir eine Leine kaufen,   Jeder ist glücklich.

     

Im zweiten Szenario habe ich dir nicht gesagt, was mein Haustier ist, wenn du es bist   Werde mir sowieso ein Geschenk kaufen, du musst Informationen wissen, die ich nicht habe   habe dir gesagt (oder rate mal), du kaufst mir eine Leine, wenn es mir wirklich gelingt   Hatte einen Hund alle sind glücklich.

     

Wenn ich jedoch tatsächlich eine Katze hatte, wissen wir jetzt, dass du eine schlechte Sache gemacht hast   Annahme (Cast) und eine unglückliche Katze an der Leine haben (Laufzeitfehler)

    
darnir 10.11.2011 02:59
quelle
0

Dies ist möglich, weil Speicher für Basis- und abgeleitete Klassen reserviert ist. In einer abgeleiteten Klasse werden die Instanzvariablen der Basisklasse zuerst zugewiesen, gefolgt von den Instanzvariablen der abgeleiteten Klasse. Wenn eine Basisklassenreferenzvariable einem abgeleiteten Klassenobjekt zugewiesen wird, sieht sie die erwarteten Basisklasseninstanzvariablen und die "zusätzlichen" abgeleiteten Klasseninstanzvariablen.

    
Holmes 31.07.2014 09:43
quelle