Vedo da this entry che l'ereditarietà virtuale aggiunge sizeof (puntatore) all'impronta di memoria di un oggetto. Oltre a questo, ci sono degli svantaggi per me semplicemente utilizzando l'ereditarietà virtuale per impostazione predefinita e l'ereditarietà convenzionale solo quando necessario? Sembra che porterebbe a un design di classe più a prova di futuro, ma forse mi manca qualche trappola.In C++, dovrei quasi sempre utilizzare l'ereditarietà virtuale?
risposta
Gli svantaggi sono che
- Tutte le classi dovranno inizializzare tutte le sue basi virtuali tutto il tempo (ad esempio se A è base virtuale di B, e C deriva da B, inoltre ha inizializzare A stesso).
- Devi usare più costoso
dynamic_cast
ovunque tu usi unstatic_cast
(potrebbe o meno il problema, a seconda del tuo sistema e se il tuo design lo richiede).
Punto 1 da solo non ne vale la pena, dal momento che non è possibile nascondere le basi virtuali. C'è quasi sempre un modo migliore.
Oh dio (1) è orribile. Grazie! Potresti essere più esplicito riguardo (2)? Vuoi dire che il compilatore genera un errore se provo a usare static_cast
@SuperElectric: perché (1) è orribile? Sarebbe meglio se un suboject di base non fosse inizializzato? ;) – Yttrill
Commenti come "non ne vale la pena" mostrano un completo fallimento nel comprendere lo scopo delle basi virtuali: l'ereditarietà virtuale deve * sempre * essere usata quando si sottoclassa un'astrazione. Non c'è soluzione alternativa o altra possibilità, se non si riesce a utilizzarlo non è possibile utilizzare più sottoclassi di astrazioni senza tornare indietro e correggere l'errore di progettazione, interrompendo così l'incapsulamento. – Yttrill
Nella mia esperienza, l'ereditarietà virtuale (al contrario dei metodi virtuali ) non è quasi mai necessaria. In C++ è usato per indirizzare lo "diamond inheritance problem", che se si evita l'ereditarietà multipla non può realmente accadere.
Sono sicuro che non ho mai riscontrato un'ereditarietà virtuale al di fuori dei libri C++, che include sia il codice che scrivo sia i milioni di sistemi di linea che mantengo.
La libreria di flussi di I/O standard C++ utilizza l'ereditarietà virtuale. Ma sì, a parte questo è in genere piuttosto raro. –
Greg: +1 ottima generalizzazione sull'intero pasticcio dell'ereditarietà virtuale. –
Hmm ... so già a cosa serve (sto pensando di usarlo), e capisco che è raro (codice in C++), ma la domanda posta era "quali sono gli svantaggi dell'ereditarietà virtuale". – SuperElectric
L'ordine di inizializzazione delle classi base diventa non ovvio per la maggior parte delle persone. Quindi aumentano i costi di manutenzione. –
L'ereditarietà virtuale aggiunge un puntatore interno solo su alcune implementazioni. Itanium ABI non usa puntatori interni, solo vptr. – curiousguy