Che cos'è una funzione virtuale?
Una funzione virtuale è una funzione, definita in una superclasse, che deve essere presente in una sottoclasse affinché quella sottoclasse abbia una definizione di classe completa. Le funzioni virtuali si basano su un paradigma di programmazione orientato agli oggetti chiamato ereditarietà virtuale, che è più comunemente visto in C ++ usando la parola chiave "virtuale". Per definire una funzione virtuale, sono necessarie due classi, una superclasse e una sottoclasse. La superclasse è dove la funzione viene prima dichiarata e possibilmente definita. La sottoclasse è dove viene definita la funzione - o sovrascritta, a seconda che la funzione sia stata definita nella superclasse.
La funzione virtuale può essere definita in due modi. Innanzitutto, può essere definito come un troncone, in cui ha un corpo vuoto e non fa nulla. In secondo luogo, potrebbe essere definito come una pura funzione virtuale, dove è definito come NULL nel file di intestazione della superclasse.
Ci sono vantaggi e svantaggi per entrambe le metodologie. La definizione di una funzione come stub assicura che tutte le sottoclassi abbiano una sua implementazione, anche se non fa nulla. Se si dimentica di sovrascrivere la funzione e implementarla correttamente in una sottoclasse, tuttavia, non appariranno errori o avvertimenti per evidenziarlo. La definizione di una funzione virtuale pura, d'altra parte, richiede che ogni sottoclasse abbia la propria definizione della funzione e, se non fosse così, appariranno degli errori.
Le funzioni virtuali, tuttavia, sono soggette alle stesse regole di ereditarietà delle funzioni non virtuali, pertanto le gerarchie di eredità con più di due livelli potrebbero non richiedere definizioni esplicite di funzioni virtuali. Ad esempio, si può considerare una classe A che dichiara una funzione virtuale, implementata nella sottoclasse B. La classe B ha una sottoclasse propria, la classe C. La classe C non richiede una definizione esplicita della funzione della classe A, perché eredita la definizione dalla classe B. Se necessario, la classe C potrebbe sovrascrivere la funzione della classe B, oppure potrebbe ignorare la funzione della classe B mentre la chiamava anche.
All'altro estremo, le funzioni virtuali non devono essere definite in una sottoclasse se sono dichiarate virtuali in quella sottoclasse. Ad esempio, si può considerare una classe A che dichiara una funzione virtuale e ha due sottoclassi, B e C. Inoltre, si potrebbe immaginare che la classe B abbia sottoclassi D ed E e la sottoclasse C abbia sottoclassi F e G.
Tutte le classi da B a G devono avere la funzione virtuale di classe A definita in qualche modo. Se la classe B ha un'implementazione della funzione A, le classi D ed E non devono essere rifatte. Forse le sottoclassi di C devono implementare la funzione di A, ma entrambe fanno qualcosa di diverso, quindi definire la funzione nella stessa classe C non sarebbe utile. In tal caso, la funzione può essere dichiarata virtuale in classe C e un'implementazione non è necessaria.
Le funzioni virtuali possono essere scoraggianti da imparare, ma se usate correttamente, possono ridurre la duplicazione del codice e rendere il codice molto più facile da capire in generale. Ci sono molte insidie con funzioni virtuali, tuttavia, in particolare per quanto riguarda l'ereditarietà multipla. In eredità multipla, è possibile che funzioni virtuali definite in modo ambiguo siano in conflitto tra loro, quindi dovrebbero essere usate con cautela in quel contesto.