Che cos’è l’ereditarietà virtuale?

L’ereditarietà virtuale è un tipo di ereditarietà in cui l’implementazione di una superclasse è incompleta ed è necessaria una sottoclasse per la definizione completa di un oggetto. Questo tipo di ereditarietà può essere utilizzato in combinazione con l’ereditarietà singola e multipla, ma è più comunemente utilizzato nell’ereditarietà multipla. Qualsiasi classe che eredita da una classe base virtuale diventa una sottoclasse diretta di quella classe base. Una classe base virtuale può fare affidamento su una sottoclasse per implementare tutti i suoi metodi, ma questo non è un requisito.

C++ è il linguaggio informatico più comunemente noto per utilizzare l’ereditarietà virtuale. Per dichiarare l’ereditarietà virtuale in C++, viene utilizzata la parola chiave “virtuale”. Sia la superclasse che la sottoclasse devono dichiarare metodi virtuali con la parola chiave “virtuale”. Questo dice al compilatore C++ che la superclasse è incompleta e che deve ottenere informazioni dalla sottoclasse per completarla. Usare la sottoclasse per completare la superclasse non significa che le sottoclassi si sovrascrivano a vicenda se hanno la stessa classe base, e invece il compilatore C++ si occupa di determinare quali pezzi vanno con ogni oggetto.

Poiché per l’ereditarietà virtuale è necessaria una classe base virtuale, le funzioni globali in C++ non possono essere dichiarate virtuali. Questo tipo di ereditarietà può essere utilizzato solo quando si aderisce ai principi della programmazione orientata agli oggetti (OOP). La ragione di ciò è che le funzioni globali non sono associate a una classe particolare e quindi sono generalmente autonome da sole. Senza una superclasse e una sottoclasse l’ereditarietà non può avvenire, quindi le funzioni globali e l’ereditarietà virtuale si escludono a vicenda. Le funzioni globali possono, in teoria, essere utilizzate all’interno delle funzioni virtuali, ma il contrario potrebbe non funzionare sempre.

L’ereditarietà virtuale viene utilizzata per risolvere molti problemi di programmazione e uno dei più utili è la risoluzione dell’ambiguità. Nell’ereditarietà multipla, si può avere una classe base A che ha due sottoclassi, B e C, e quindi una classe D che eredita da entrambe le classi B e C. Questo modello è comunemente chiamato “diamante della morte” perché se le classi A, B e C hanno tutte implementazioni dello stesso metodo, non è possibile per la classe D determinare quale implementazione dovrebbe usare. L’ereditarietà virtuale risolve questo problema perché l’implementazione di ogni classe rimane distinta e quindi non ambigua. Questa distinzione è gestita da oggetti interni specializzati chiamati tabelle virtuali (vtables) che tengono traccia di ogni tipo di oggetto, ma queste tabelle non hanno bisogno di essere manipolate esplicitamente da un programmatore perché sono integrate nel linguaggio.