2011-11-10 15 views
8

Sono stato un codificatore .Net (non posso dire di essere un programmatore) per 2 anni. C'è una domanda che non riesco a capire da anni, cioè come può un'istanza della classe base contenere un'istanza della classe derivata?In che modo un'istanza della classe base può contenere un'istanza della classe derivata?

Supponiamo di avere due classi:

class BaseClass 
{ 
    public A propertyA; 
    public B propertyB; 
} 

class DerivedClass :BaseClass 
{ 
    public C propertyC; 

} 

come è potuto accadere:

BaseClass obj = new DerivedClass() 

Voglio dire, il modello di memoria di BaseClass, non ha spazio per il propertyC appena aggiunto, così come potrebbe conserva ancora il valore della proprietà C?

D'altra parte, come potrebbe questo non può accadere:

DerivedClass obj = new BaseClass() 

ho pensato che questo è il modo corretto in quanto il modello di memoria di DerivedClass ha tutti gli spazi per la BaseClass e anche di più. Ma questo non è vero, perché?

So che sto facendo una domanda davvero stupida, ma qualcuno potrebbe darmi una risposta più dettagliata di questo? Sarebbe meglio dal punto di vista della memoria o del compilatore.

+0

Questo è esattamente lo stesso di questa domanda qui, con una risposta molto ben scritta alla tua domanda. http://stackoverflow.com/questions/4937180/a-base-class-pointer-can-point-to-a-derived-class-object-why-is-the-vice-versa – darnir

+0

Grazie a tutti per il vostro eccellente risposte! Ho capito :) Grazie a tutti !!! ~ – NextStep

risposta

5

Perché (e questo concetto è spesso frainteso) la variabile che contiene il puntatore viene digitata indipendentemente dal tipo concreto effettivo dell'oggetto a cui punta.

Quindi, quando si scrive

BaseClass obj = new DerivedClass() 

la parte che dice BaseClass obj crea un nuovo riferimento variabile sullo stack che il compilatore capisce per contenere un riferimento a qualcosa che è, o deriva, da BaseClass.

La parte che legge = new DerivedClass() in realtà crea un nuovo oggetto di tipo DerivedClass, lo memorizza sul mucchio, e memorizza un puntatorea quell'oggetto nella locazione di memoria che obj punti. L'oggetto effettivo nell'heap è unDerivedClass; questo è indicato come il tipo di calcestruzzo dell'oggetto.

La variabile obj è dichiarata di tipo BaseClass. Questo non è un tipo concreto , è solo un tipo variabile, che limita solo al compilatore di memorizzare un indirizzo nella variabile che indica un oggetto che non è un BaseClass o che non deriva dal tipo BaseClass.

Questo viene fatto per garantire che ciò che si mette nella variabile obj, non importa se si tratta di un tipo concreto di BaseClass o DerivedClass, avrà tutti i metodi, le proprietà e gli altri membri del tipo BaseClass. Indica al compilatore che tutti gli usi della variabile obj devono essere limitati agli usi solo dei membri della classe BaseClass.

4

Poiché BaseClass è un tipo di riferimento, obj non è un oggetto . È un riferimento a un oggetto BaseClass. In particolare, si tratta di un riferimento alla parte BaseClass di DerivedClass.

+0

Dopo aver capito tutte le altre risposte, ho capito il vostro punto :) Grazie. – NextStep

2

Quando si dice questo:

BaseClass obj = new DerivedClass() 

NON dici "creare un contenitore per contenere questo oggetto BaseClass, e poi stipare DerivedClass questo più grandi oggetto in esso".

Si sta infatti creando un oggetto DerivedClass e viene creato in uno spazio di memoria sufficiente per un oggetto DerivedClass. Mai il framework .NET perde la cognizione del fatto che questa cosa è specificamente una DerivedClass, né smette mai di trattarla come tale.

Tuttavia, quando si dice di utilizzare una variabile oggetto BaseClass, si sta solo creando un riferimento/puntatore a quell'oggetto che è già stato creato, assegnato e definito e tutto ciò, e il puntatore è solo un po 'di più vago.

È come quel tizio laggiù dall'altra parte della stanza è un contadino di pollo leggermente sovrappeso irlandese dai denti rossi con i denti stretti e la personalità affascinante di nome Jimmy, ma tu ti riferisci solo a lui come "quel tipo Là". Il fatto che tu sia vago nel descriverlo non cambia quello che è o uno dei suoi dettagli, anche se la tua vaga descrizione è del tutto accurata.

+0

Questa è davvero una risposta divertente e facile da capire.Grazie! :) – NextStep

+0

+1 per l'esempio! – Lazer

0

Answer copiato verbatim da quello che un altro utente, jk, ha scritto su una stessa identica domanda qui su Stackoverflow.

Se ti dico che ho un cane, puoi tranquillamente pensare di avere un cane.

Se ti dico che ho un animale domestico, non sai se quell'animale è un cane, lo potrebbe essere un gatto o forse anche una giraffa. Senza conoscere alcune informazioni aggiuntive su , non si può presumere che abbia un cane.

analogamente un oggetto derivato è un oggetto di classe base (come una classe sub ), quindi può essere puntato da un puntatore di classe base. tuttavia un oggetto di classe di base non è un oggetto di classe derivato, pertanto non può essere assegnato a un puntatore di classe derivato .

(lo scricchiolio si sente ora è l'analogia che si estende)

Supponiamo ora mi vuoi comprare un regalo per il mio animale domestico.

Nel primo scenario sai che è un cane, puoi comprarmi un guinzaglio, tutti sono felici.

Nel secondo scenario che non ti ho detto qual è il mio animale domestico è quindi se siete intenzione di comprarmi un regalo in ogni caso è necessario conoscere le informazioni I havent ti ha detto (o solo indovinare), mi si acquista un guinzaglio, se risulta che io in realtà ho un cane tutti sono felici.

Tuttavia, se ho effettivamente avuto un gatto quindi ora sappiamo che hai fatto una brutta presupposto (Cast) e hanno un gatto infelice al guinzaglio (errore di runtime)

+0

Ho capito anche tu, grazie :) – NextStep

0

Ciò è possibile a causa della memoria di modo è allocato per classi base e derivate. In una classe derivata, le variabili di istanza della classe base vengono allocate per prime, seguite dalle variabili di istanza della classe derivata. Quando una variabile di riferimento della classe base viene assegnata a un oggetto classe derivata, vede le variabili di istanza della classe base che si aspetta più le variabili di istanza della classe derivate "extra".

Problemi correlati