Un po 'confuso con le funzioni virtuali

1

Vedi il seguente codice:

#include<iostream.h>
#include<string.h>
class father
{
    char fname[20];
    public:
        father()
        {
            strcpy(fname,"eshwarappa");
        }
        void show()
        {
            cout<<"Father's name = "<<fname<<endl;
        }
};
class son: public father
{
    char sname[20];
    public:
        son()
        {
            strcpy(sname,"yajurappa");
        }
        void show()
        {
            cout<<"Son's name = "<<sname<<endl;
        }
};
int main()
{
    father *bp;
    father f;
    bp=&f;
    bp->show();
    son s;
    bp=&s;      //Valid assignment
    bp->show();
}

USCITA:

Father's name = eshwarappa
Father's name = eshwarappa

Perché il puntatore della classe base bp effettua una chiamata alla classe base 'metodo show () anche quando contiene l'indirizzo dell'oggetto figlio della classe derivata.

P.S. So che questo può essere risolto rendendo la funzione show () come virtuale nella classe base, ma voglio solo sapere perché non funziona in questo modo.

    
posta Harsh Gupta 13.05.2015 - 20:55
fonte

1 risposta

8

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.

    
risposta data 13.05.2015 - 21:09
fonte

Leggi altre domande sui tag