Oppure

Loading
14/06/10 10:11
Premoli
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:

codepad.org/…

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:

codepad.org/…

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...
aaa
14/06/10 12:29
TheKaneB
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.
aaa
14/06/10 13:31
Premoli
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?
aaa
14/06/10 13:50
TheKaneB
evidentemente la base viene ereditata una volta sola grazie ad un'ottimizzazione del compilatore, anche se poi fa finta di averla ereditata 2 volte...
aaa
14/06/10 14:09
Premoli
ah, ok grazie mille per i chiarimenti ;)
aaa