Funzioni virtual

di il
73 risposte

73 Risposte - Pagina 2

  • Re: Funzioni virtual

    Esatto
  • Re: Funzioni virtual

    Ok, allora l'overriding serve per ridefinire un metodo in una classe derivata, mentre l'overloading serve per chiamare un metodo con lo stesso nome di un altro cambiando la firma (numero o tipo dei parametri passati)

    giusto?
  • Re: Funzioni virtual

    Assolutamente si.
  • Re: Funzioni virtual

    E ora nel dettaglio il polimorfismo in quali casi si usa?
  • Re: Funzioni virtual

    Inizio a farti un esempio in cui non si usa il polimorfismo ma solo l' override:
    
    class Animale
    {
    public:
    	void Parla() 
    	{
    		cout << "Sgrunf" << endl;
    	}
    };
    
    class Gatto: public Animale
    {
    public:
    	void Parla()
    	{
    		cout << "Miao" << endl;
    	}
    };
    
    int main()
    {
    	Animale animale;
    	animale.Parla();   // sgrunf
    
    	Gatto gatto;
    	gatto.Parla();   // miao
    
    	animale = gatto;
    	animale.Parla();  // ancora sgrunf
    	return 0;
    }
    
    Come vedi nonostante alla variabile animale abbia alla fine assegnato un gatto, questa non ha miagolato. (prova ad eseguirlo e ti convincerai).

    Questo è override e non c' entra col polimorfismo.

    Quello che invece vogliamo ottenere è un animale che quando gli assegni un gatto miagola e quando gli assegni un cane abbaia. Dimmi quando posso proseguire.
  • Re: Funzioni virtual

    È vero però perché questo ?
  • Re: Funzioni virtual

    Dato che manca il virtual, Il collegamanto ai metodi viene effettuato a compile-time per cui le istanze di Animale non sono polimorfe e faranno sempre 'Sgrunf'.

    La parola polimorfismo significa 'che ha forme diverse', quando fai diventare un oggetto polimorfo (aggiungendo virtual ai suoi metodi) informi il compilatore che invece vuoi un comportamento particolare.
  • Re: Funzioni virtual

    Quindi in pratica la maggior parte delle volte che si usa l'override si usa di conseguenza anche la virtual( e quindi il polimorfismo)
  • Re: Funzioni virtual

    Si, non è una regola obbligatoria ma solitamente fare l' override senza il virtual porta a incomprensioni ed errori.

    Ti metto il codice dell' esempio che miagola:
    
    class Animale
    {
    public:
    	void virtual Parla() 
    	{
    		cout << "Sgrunf" << endl;
    	}
    };
    
    class Gatto: public Animale
    {
    public:
    	void virtual Parla()
    	{
    		cout << "Miao" << endl;
    	}
    };
    
    class Cane: public Animale
    {
    public:
    	virtual virtual void Parla()
    	{
    		cout << "Bau" << endl;
    	}
    };
    
    int main()
    {
    	Gatto gatto;
    	Cane cane;
    
    	Animale* animale;
    	
    	animale = &gatto;
    	animale->Parla();   // miao;
    
    	animale = &cane;
    	animale->Parla();   // bau
    
    	return 0;
    }
    
    Come vedi ho messo il virtual ed usato i puntatori.
  • Re: Funzioni virtual

    Ok però ho un dubbio, cioè quando si usa virtual bisogna necessariamente usare i puntatori? no perché sul mio libro c'è un esempio con le virtual ma senza i puntatori, eccolo:

    http://imageshack.us/photo/my-images/402/img0997h.jpg

    http://imageshack.us/photo/my-images/17/img0998mp.jpg
  • Re: Funzioni virtual

    E infatti nessuno si comporta in maniera polimorfa, il rettangolo si comporta come un rettangolo e il triangolo rettangolo come un triangolo rettangolo. Prova a togliere i virtual da quell' esempio e vedrai che non cambia niente. Probabilmente il libro vuole introdurti le cose poco alla volta.
    ---
    Il motivo per cui si usano i puntatori è legato alle dimensioni delle classi.

    Quando dichiari una variable con 'Gatto gatto' allochi nello stack una variabile che contiene un gatto, quando dichiari 'Gatto* gatto = new Gatto()' allochi nello stack un puntatore che punta ad una zona di memoria (lo Heap) che contiene il gatto.

    Considera queste classi:
    
    class Rettangolo
    {
    public:
        int lunghezza;
        int altezza;
    };
    
    class Parallelepipedo: public Rettangolo
    {
    public:
        int profondita;
    };
    
    un Rettangolo ha i campi Lunghezza e Altezza, un parallelepipedo aggiunge la Profondità.

    Quindi lo spazio necessario in memoria per contenere un rettangolo è di 8 bytes (4 byte per ogni intero) mentre per un parallelepipedo ne servono 12.

    È evidente che dentro la zona di memoria che contiene un rettangolo non possiamo infilare un Parallelepipedo (che è più grande).
    Diverso è il discorso con i puntatori, se prima un puntatore punta ad una zona di memoria contenente un rettangolo non c' è nessun problema a spostare il puntatore e farlo puntare ad una zona di memoria contenente un parallelepipedo.

    In alcuni linguaggi (Java, C#) l' uso dei puntatori viene nascosto, per cui si scrive:
    
       Gatto gatto = new Gatto();
       gatto.Parla();
    
    Ma il loro uso e solo nascosto in realtà sono puntatori.
  • Re: Funzioni virtual

    A ecco quindi ad esempio in vb.net e nei linguaggi che hai detto non esiste il discorso delle funzioni virtuali e del collegamento dinamico.giusto?
  • Re: Funzioni virtual

    No, sbagliato.
    In VisualBasic, C#, Java è lo stesso identico meccanismo. Il collegamento è sempre dinamico. La differenza sta nella sintassi del linguaggio che ti nasconde il fatto che stai usando dei puntatori (ma li stai usando). Poi ogni linguaggio ha delle sue peculiarità, ad esempio in Java tutti i metodi sono virtuali, ma il principio è lo stesso.
  • Re: Funzioni virtual

    A ecco pero diciamo che fa tutto lui , quindi se faccio un'assegnazione che hai fatto prima tra due oggetti non ci sará nessun problema ed equivoco nel richiamo dei metodi
  • Re: Funzioni virtual

    Esatto, infatti lavorare in .NetFramework è molto più rilassante, fai meno errori e vai più veloce. Tu conosci il VisualBasic e il C++, in pratica potresti anche usare il C# senza problemi.
Devi accedere o registrarti per scrivere nel forum
73 risposte