Un puntatore al subobject della classe base.Per un oggetto di classe "studente", perchè la sizeof restituisce 12 byte? Cosa viene aggiunto?
Stesso dicasi per la classe "lavoratore" e per la classe "studente_lavoratore". Cosa viene aggiunto?
Prendiamo studente:
il suo layout di fatto sarà equivalente a qualcosa di questo tipo:codice:class studente:virtual public persona { protected: int s; };
con _studente_baseptr che viene inizializzato a &_base al momento della costruzione; lo stesso dicasi per lavoratore.codice:struct studente { persona *_studente_baseptr; int s; persona _base; }
Per studente_lavoratore, la questione sarà di questo tipo:
Anche qui, i due baseptr vengono inizializzati a _base al momento della costruzione.codice:struct studente_lavoratore { // subobject studente persona *_studente_baseptr; int s; // subobject lavoratore persona *_lavoratore_baseptr; int l; // subobject classe base condivisa persona _base; };
Qual è lo scopo di tutto questo giro di puntatori? Per fare in modo che codice che si aspetta uno studente* possa funzionare correttamente con uno studente_lavoratore, facendo riferimento al subobject di classe base corretto in ogni caso.
Immaginiamo che il compilatore debba compilare del codice di questo tipo:
Il codice diventa del tipo:codice:void foo(studente *s) { s->p = 12; } void bar(lavoratore *l) { l->p = 24; } int main() { studente s; studente_lavoratore sl; foo(&s); foo(&sl); return 0; }
Il codice di foo viene compilato una sola volta, indipendentemente dal tipo della classe derivata che può essere passato (in cui la posizione del subobject di classe base può variare), ma dato che tutti i riferimenti alla classe base avvengono in modo indiretto tramite il puntatore il risultato finale è sempre corretto. Nota tra l'altro che per passare uno studente_lavoratore ad una funzione che si aspetta un lavoratore * il compilatore deve aggiustare il puntatore prima del passaggio (deve passare un puntatore al primo membro del subobject di tipo lavoratore), ma a parte questo funzioni che si aspettano un lavoratore * funzionano in maniera trasparente.codice:void foo(studente *s) { s->_studente_baseptr->p = 12; } void bar(lavoratore *l) { s->_lavoratore_baseptr->p = 12; } int main() { studente s; s._studente_baseptr = &s._base; studente_lavoratore sl; s._studente_baseptr = &sl._base; foo(&s); foo(&sl); bar((lavoratore *)&_lavoratore_baseptr); return 0; }

Rispondi quotando