Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - ereditarietà
Forum - C/C++ - ereditarietà

Avatar
Premoli (Normal User)
Pro


Messaggi: 108
Iscritto: 25/06/2009

Segnala al moderatore
Postato alle 12:11
Lunedì, 14/06/2010
ciao a tutti!!!

Stavo studiando un po' il c++ e arrivato all'ereditarietà sto trovando difficoltà a capire una cosa:

Quando vengono ereditate più classi base viene introdotto un elemento di ambiguità, infatti in questo programma:

http://codepad.org/utWpwAqu

la classe base è ereditata sia da derived1 che da derived2 successivamente derived3 eredita sia derived1 che derived2 quindi in derived3 sono presenti due copie di base pertanto se nel main scrivessi:

derived3 O;

O.i=30;

verrebbe generato un errore perché i è ambiguo, il tutto si potrebbe risolvere o applicando l'operatore :: però così l'oggetto avrebbe ancora due copie di base, oppure si potrebbero usare classi basi virtuali come in questo caso:

http://codepad.org/FO5QkdWf

quindi credo che fin qui sia tutto giusto, il dubbio mi sorge riguardo alla sizeof()

nel primo caso si ha:

sizeof(base)=4; ok giusto contiene solo un int
sizeof(derived1)=8 e sizeof(derived2)=8 ok anche in questo caso
invece non riesco a capire perché sizeof(derived3)=20

nel secondo caso le cose mi sono ancora meno chiare infatti ereditando base come virtual i risultati sono questi:

sizeof(base)=4; ok...
sizeof(derived1) e sizeof(derived2)=12 perché?
sizeof(derived3)=24 perché?

chiedo scusa per la lunghezza del post... e vi ringrazio anticipatamente per le eventuali risposte...

PM Quote
Avatar
TheKaneB (Member)
Guru^2


Messaggi: 1792
Iscritto: 26/06/2009

Segnala al moderatore
Postato alle 14:29
Lunedì, 14/06/2010
il discorso dell'ambiguità è intrinseco nell'ereditarietà multipla, e non ci puoi fare niente. E' uno degli svantaggi dei linguaggi come C++, che viene brillantemente risolto in Object-Pascal, in Modula-2 e in Java con l'utilizzo dei cosiddetti Components, che implementano delle interfacce astratte piuttosto che ereditare classi instanziabili.

Per quanto riguarda il sizeof() di una classe, intervengono 2 fattori che non puoi controllare direttamente:

1- la Virtual Table, contiene i puntatori a tutte le funzioni virtuali di quella classe, la sua dimensione è variabile
2- il Padding, sono byte vuoti che il compilatore inserisce per allineare gli indirizzi dei membri delle classi a multipli di 4 byte, in modo da velocizzare gli accessi in memoria e (in alcune architetture RISC) evitare il disallineamento dello stack con conseguente corruzione dello stesso.

PM Quote
Avatar
Premoli (Normal User)
Pro


Messaggi: 108
Iscritto: 25/06/2009

Segnala al moderatore
Postato alle 15:31
Lunedì, 14/06/2010
ciao TheKaneB e grazie per avermi risposto...

Vabbè comunque anche in c++ come avevo già scritto il problema si può risolvere... o mi sbaglio?

per quanto riguarda la sizeof() il discorso delle v-table si ha solo nel secondo caso quando eredito base come virtual, quindi quei byte in più sono occupati dai puntatori?

nel primo caso invece non dovrebbe esserci questo problema e non dovrebbe presentarsi neanche quello dell'allineamento dato gli gli int sono di 4 byte...

quindi perché la sizeof(derived3) è 20?

non doveva essere 24? 8 per derived2 8 per derived1 4 per base e altri 4 sempre per base dato che viene ereditata 2 volte?

PM Quote
Avatar
TheKaneB (Member)
Guru^2


Messaggi: 1792
Iscritto: 26/06/2009

Segnala al moderatore
Postato alle 15:50
Lunedì, 14/06/2010
evidentemente la base viene ereditata una volta sola grazie ad un'ottimizzazione del compilatore, anche se poi fa finta di averla ereditata 2 volte...

PM Quote
Avatar
Premoli (Normal User)
Pro


Messaggi: 108
Iscritto: 25/06/2009

Segnala al moderatore
Postato alle 16:09
Lunedì, 14/06/2010
ah, ok grazie mille per i chiarimenti ;)

PM Quote