Ho trovato alcune altre domande che sembrano implicare la mia domanda, ma nessuna ha risposto direttamente (anche the one con quasi lo stesso nome).Perché l'upcasting di un puntatore figlio a una classe base a volte cambia il valore del puntatore?
Ho una classe figlio C++ derivata da due genitori. Creo un oggetto di quella classe, quindi lancio il suo riferimento a ciascuno dei suoi due genitori. I valori cast non sono gli stessi, sebbene uno rimanga il valore del riferimento figlio. Ecco il codice:
class Mom
{
public:
int a = 1;
};
class Dad
{
public:
int b = 2;
};
class Child : public Mom, public Dad
{
public:
int c = 3;
};
int main()
{
Child* c = new Child; // 0x00C5A618
Mom* m = c; // 0x00C5A618
Dad* d = c; // 0x00C5A61C
return 0;
}
Ora, sto indovinando che gli indirizzi ottenuti applicando static_cast <> sono quelle degli oggetti secondari attuali. Come succede, Mom
è il primo subobject, quindi in realtà ha lo stesso indirizzo di Child
. Dad
è il secondo subobject, quindi risiede su un indirizzo diverso.
Da quanto ho capito, in stile C calchi, come questo
Mom* m = (Mom*)c;
Dad* d = (Dad*)c;
si applicherà uno static_cast <> quando sarebbe legale per farlo. Infatti, quando effettivamente compilo ed eseguo quella versione, vedo lo stesso comportamento di prima.
Continuando questa saga scintillante, con cast impliciti, come questo
Mom* m = c;
Dad* d = c;
lo stesso comportamento pure, da cui deduco che cast impliciti si applicano anche static_cast <> quando il cast esplicito equivalente sarebbe legale.
downcasting torna a Child
fa la stessa cosa:
Child* k = static_cast<Child*>(d); // 0x00C5A618
Il valore in k
è diverso dal valore in d
, essendo stato arretrato al valore originariamente nel c
.
sto indovinando che, in questo caso, non v'è un controllo in fase di esecuzione per vedere se, in effetti, d
punti per un Dad
sotto-oggetto di un oggetto Child
.
Finora, tutto questo ha senso, ma sono sorpreso che non ci sia una tale regolazione degli indirizzi (se è la cosa giusta chiamarla) per le gerarchie derivate singolarmente. Cioè, se la mia gerarchia è semplicemente Mom
->Dad
->Child
, lanciando un riferimento a un Child
in un puntatore, o un Mom
o un Dad
non cambia mai il valore:
class Mom
{
public:
int a = 1;
};
class Dad : public Mom
{
public:
int b = 2;
};
class Child : public Dad
{
public:
int c = 3;
};
int main()
{
Child* c = new Child; // 0x00C5A618
Mom* m = c; // 0x00C5A618
Dad* d = c; // 0x00C5A618
Child* k = static_cast<Child*>(d); // 0x00C5A618
return 0;
}
mi sarei aspettato che per modificare la dimensione della memoria necessaria per ogni sottoclasse aggiuntiva o quattro byte (la dimensione di un int). Ma loro non lo fanno. Tutti i puntatori nell'esempio sopra riportato, c
, m
, d
e k
, hanno lo stesso valore.
Così, ora sto indovinando che gli oggetti sono stati disposti in memoria con l'oggetto Mom
presso l'indirizzo più basso, il ulteriore spazio necessario per l'oggetto Dad
accadrà dopo, e il ulteriore spazio necessario per il Child
venendo scorso. Dal momento che un numero Dad
è un Mom
, l'indirizzo Dad
sarebbe lo stesso dell'indirizzo Mom
, no?
Allo stesso modo, un Mom
è anch'esso un Mom
, quindi il suo indirizzo sarebbe anche lo stesso del proprio indirizzo Mom
subobject.
Quindi ...
Penso che sta lavorando in questo modo: in memoria, gli oggetti si susseguono in modo tale che, nel puramente singolarmente derivato gerarchia, upcasting e downcasting sempre produce lo stesso indirizzo, mentre in un moltiplicano gerarchia derivata, alcuni upcast producono un indirizzo diverso, perché non tutti i sottooggetti inizieranno dallo stesso indirizzo dell'oggetto derivato. Come questo:
Possible Memory Layout for a Singly Derived Hierarchy
+-------+-----+-----+---+
| Child : Dad : Mom : a |
| | +-----+---+
| | : b |
| +-----------+---+
| : c |
+-----------------------+
Possible Memory Layout for a Multiply Derived Hierarchy
+-------+-----+---+
| Child : Mom : a |
| +-----+---+
| : Dad : b |
| +-----+---+
| : c |
+-----------------+
dispiace che ho divagato un po ', ma la mia domanda è questa: è il fatto che un upcast ad alcune classi di base di un oggetto si moltiplicano derivato cambia il valore del riferimento a seguito del Infatti il valore post-cast è l'indirizzo dell'oggetto base in memoria?
Sì ........... – Soren