Perché eseguire una funzione virtuale comporta un costo di runtime diverso da zero. Parte della filosofia di C ++ è "paghi solo ciò che usi"; ad esempio, non paghi il costo di una funzione virtuale a meno che tu non ne abbia esplicitamente richiesto la scrittura scrivendo virtual
nel codice.
Per quanto riguarda il motivo per cui questo costo di esecuzione, la risposta breve è che un puntatore father
di per sé non dice se sta effettivamente puntando a father
o a son
o qualche altra classe derivata. L'unico modo per sapere che tipo in realtà punta a in fase di runtime è per ogni oggetto father
di portare in giro una porzione di dati in più che identifica di che tipo si tratta. Ciò significa che gli oggetti con metodi virtuali occupano (leggermente) più memoria.
Nella maggior parte delle implementazioni quel dato extra è un singolo puntatore a un "vtable". Se hai dato father
a un metodo virtuale, allora ogni father
oggetto che viene creato in fase di esecuzione avrà un puntatore al father
vtable e ogni son
oggetto che verrà creato in fase di esecuzione avrà un puntatore alla son
vtable. Supponendo che show()
sia l'unico metodo virtuale, entrambi i vtables conterranno un singolo puntatore a funzione delle rispettive implementazioni di show()
. Ciò significa dereferenziare alcuni puntatori ogni volta che chiami show (), il che significa che i metodi virtuali possono essere (leggermente) più lenti dei metodi non virtuali.
Si potrebbe obiettare che un puntatore in più su ogni oggetto e un po 'più puntatore di inseguitori non è un costo significativo. Questo dipende dalla classe e dall'applicazione. Se stai facendo calcoli scientifici con matrici 1000x1000, potresti non voler aggiungere 4 byte aggiuntivi su ogni singolo oggetto matrice / vettoriale / etc e un paio di dereferenze extra su ogni operazione di addizione / moltiplicazione / divisione. C ++ ti consente di decidere esattamente quando quel costo ha e non ha importanza.
D'altra parte, alcuni altri linguaggi OOP (in genere quelli con garbage collection) hanno scelto di rendere tutto "virtuale di default". È un compromesso.