2012-10-31 20 views
9

Il seguente codice sono tratti dal libro "Dentro modello a oggetti C++"Domande su C++ Inheritance virtuale

#include <iostream> 
using namespace std; 
class X{}; 
class Y: public virtual X{}; 
class Z: public virtual X{}; 
class A: public Y, public Z{}; 

int main() 
{ 
    cout<<sizeof(X)<<" "<<sizeof(Y)<<" "<<sizeof(Z)<<" "<<sizeof(A)<<endl; 
    return 0; 
} 

nel mio computer (Windows, VS2010), l'output è:

Here're mie domande

1, sizeof (X) = 1

Il libro dicono s quando il tipo X genera due istanze, ad esempio xa e xb. la compilazione inserisce un byte in A in modo che xa e xb possano avere indirizzi diversi. Non capisco le ragioni.

2, sizeof (Y) = 4

Utilizzando l'ereditarietà virtuale, avremo un puntatore virtuale aggiuntivo? Immagino che questo potrebbe essere diverso dal puntatore virtuale nel polimorfismo. Qualcuno può darmi il layout di memoria per Y?

Grazie!

+0

Una domanda per domanda per favore –

+0

per la 1a domanda, controllare: http://stackoverflow.com/questions/621616/c-che-è-la-size-di-an- object-of-an-empty-class? rq = 1 –

+1

Penso che la tua domanda principale sia quella in cui Y usa l'ereditarietà virtuale per derivare da una classe non polimorfica X, e Y stessa non è polimorfica, sarà l'ereditarietà stessa del virus Y per avere un v-table quindi la sua dimensione è 4 .. – CashCow

risposta

6
  1. compilatore nuovo char quando la classe è vuota, in modo che possa generare oggetto diverso
  2. sizeof (Y) = 4 perché è virtuale ereditarietà, costrutto genererà vptr table che è 4 byte sul sistema a 32 bit
  3. se si utilizza Visual Studio use/d1reportAllClassLayout in proprietà-> C/C++/Command per generare il layout dell'oggetto il layout dell'oggetto di classe Y sarà su Visual Studio:
  4. libro 'All'interno C++ modello oggetto' da Stanley B. Lippman spiegato questo estremamente ben


     class Y size(4): 
      +--- 
      0  | {vbptr} 
      +--- 
      +--- (virtual base X) 
      +---
Y::[email protected]: 0 | 0 1 | 4 (Yd(Y+0)X)

vbi: class offset o.vbptr o.vbte fVtorDisp X 4 0 4 0
1

sizeof di una classe vuota restituisce sempre 1. Quello è un singolo byte fittizio per una classe vuota.

A contiene le due voci nella tabella virtuale, uno per Y altro per Z

Così i sizeof due puntatori ie 8.

Y e Z tenere entrambi hanno una singola entrata di X la tabella virtuale, quindi la dimensione è 4.

+0

Non vedo le classi chiamate B e C qui – CashCow

1

un un oggetto includerà un oggetto Y, un oggetto Z (in questo ordine) e solo uno X oggetto (a cui fanno riferimento i puntatori in Y e Z), perché sia Y che Z ereditano virtualmente da X, il che significa che quando l'ereditarietà multipla viene a giocare, solo un oggetto X sarà istanziato all'interno delle classi figlio. A ha ancora due oggetti (uno Y, uno Z) e quindi ha sizeof = 8 (poiché entrambi hanno sizeof = 4). Ma entrambi i puntatori in Y e Z sull'oggetto X punteranno allo stesso indirizzo.

L'albero eredità sarà assomigliare:

X 
/\ 
Y Z 
\/
    A 
0

La ragione classi -must- essere di almeno 1 byte è dire che abbiamo una serie di X.Se fossero 0 byte allora l'array & [1] avrebbe lo stesso indirizzo di & array [3] che nessuno si aspetterebbe, romperebbe il codice, sarebbe fastidioso se si dovesse scrivere codice per verificarlo e in genere non lo farà alcun senso.

Y sarebbe semplicemente

static void* virtual_ptr1 //note this is in virtual table and cannot be edited 

si può pensare di VTables (puntatori virtuali per classi e funzioni virtuali) come variabili statiche che non è possibile modificare a mano/code (o almeno non dovrebbe). Pensateci come variabili statiche riservate del compilatore

+1

Mi piace questa spiegazione per il motivo sizeof (X) = 1 – Junjie