Condividi tramite


Classi di base virtuali

Poiché la classe può essere una classe base indiretta a una classe derivata più volte, C++ consente di ottimizzare la modalità di utilizzo di classi di base.Le classi di base virtuali offrono un modo per risparmiare spazio e evitare le ambiguità in gerarchie di classi che viene utilizzata l'ereditarietà multipla.

Ogni oggetto non virtuale contiene una copia dei membri dati definiti nella classe base.Questa duplicazione spreca lo spazio e richiede di specificare che la copia dei membri della classe base si desidera ogni volta che si accede.

Quando una classe base è specificata come base virtuale, può fungere più volte da base indiretta senza duplicazione dei relativi membri dati.Una sola copia dei relativi membri dati è condivisa da tutte le classi di base che la utilizza come base virtuale.

Nella dichiarazione di una classe base virtuale, virtuale la parola chiave viene visualizzato negli elenchi di base delle classi derivate.

Si consideri la gerarchia di classi nella figura seguente, che viene illustrata una riga simulata di pranzo.

Grafico simulato di Pranzo-Linea

Rappresentazione grafica di oggetto Lunch-Line simulato

Nella figura, Queue è la classe base per entrambi CashierQueue e LunchQueue.Tuttavia, quando entrambe le classi combinati per formazione LunchCashierQueue, il successivo problema: la nuova classe contiene due oggetti subordinati di tipo Queue, uno da CashierQueue e l'altro da LunchQueue.Nella figura seguente viene illustrato il layout concettuale di memoria (il layout effettivo di memoria può essere specificata).

Oggetto simulato di Pranzo-Linea

Oggetto Lunch-Line simulato

Si noti che sono presenti due Queue oggetti subordinati in LunchCashierQueue oggetto.Il codice seguente viene dichiarato Queue per essere una classe base virtuale:

// deriv_VirtualBaseClasses.cpp
// compile with: /LD
class Queue {};
class CashierQueue : virtual public Queue {};
class LunchQueue : virtual public Queue {};
class LunchCashierQueue : public LunchQueue, public CashierQueue {};

virtual la parola chiave in modo che solo una copia del sotto-oggetto Queue è incluso (vedere la figura seguente).

Oggetto simulato di Pranzo-Linea con le classi di base virtuali

Oggetto Lunch-Line simulato di classi VS

La classe può disporre sia un componente virtuale che un componente non virtuale di un tipo specificato.Ciò si verifica in condizioni illustrate nella figura che segue.

Componenti virtuali e non virtuali della stessa classe

Componenti delle stesse classi virtuali e non virtuali

Nella figura, CashierQueue e LunchQueue utilizzo Queue come classe base virtuale.tuttavia, TakeoutQueue specifica Queue come classe base, non una classe base virtuale.di conseguenza, LunchTakeoutCashierQueue dispone di due oggetti subordinati di tipo Queue: uno dal percorso dell'ereditarietà che includa LunchCashierQueue e uno dal percorso che include TakeoutQueue.Tale situazione è illustrata nella figura che segue.

Layout dell'oggetto tramite l'ereditarietà virtuale e non virtuale

Grafica Virtual_NonvirtualInheritanceObjectLayout

[!NOTA]

L'ereditarietà virtuale offre vantaggi significativi di dimensione in paragone per l'ereditarietà non virtuale.Tuttavia, può introdurre un ulteriore sovraccarico di elaborazione.

Se una classe derivata esegue l'override di una funzione virtuale che eredita da una classe base virtuale e se un costruttore o un distruttore per le chiamate derivate dalla classe base che funzionano tramite un puntatore alla classe di base virtuale, il compilatore può introdurre i campi nascosti aggiuntivi “vtordisp in„ classe con basi virtuali.L'opzione /vd0 del compilatore elimina l'aggiunta del membro nascosto di navigazione del costruttore e/o distruttore vtordisp.L'opzione del compilatore /vd1, l'impostazione predefinita, consente in cui sono necessari.Disattivare i vtordisps solo se si è certi che tutti i costruttori di classe e distruttori chiamano funzioni virtuali virtualmente.

L'opzione del compilatore /vd su un intero form di compilazione.utilizzare vtordisp pragma per eliminare e quindi riabilitare i campi vtordisp nella classe-da-classe:

#pragma vtordisp( off )
class GetReal : virtual public { ... };
#pragma vtordisp( on )

Vedere anche

Riferimenti

Più classi base