Classi c++

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Avatar utente
durzino
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 872
Iscrizione: mercoledì 5 luglio 2006, 21:14

Classi c++

Messaggio da durzino »

Salve ragazzi, volevo chiedere una mano a qualcuno nel campo liste c++.
Guardate l'esercizio 5 di questo esame passato http://www2.ing.unipi.it/~d8669/didatti ... 7-2008.pdf

quando nell'int main mi dice A*pa=new c(3); do il giusto output, poi alla riga dopo mi dice pa->f() ma qui a quale funzione si riferisce d quale classe? E per quanto riguarda i disruttori in che ordine verngono chiamati?
spero mi sapete aiutare...
...Meglio un terminale oggi Che un Crash oggi e domani...E dopodomani....
Avatar utente
daemon_nio
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1012
Iscrizione: lunedì 15 gennaio 2007, 14:18
Sesso: Maschile
Località: London
Contatti:

Re: Classi c++

Messaggio da daemon_nio »

Allora cerco di commentarti un po' il codice e il risultato:

l'istruzione

Codice: Seleziona tutto

A* pa = new C(3);
produce:

Codice: Seleziona tutto

A : a = 3
B: b = 3
A : a = 0
C: a = 4
Dove la prima, seconda e quarta istruzione sono facilmente intuibili (c'ero arrivato anche senza eseguire il codice ;) ), infatti sono le chiamate ricorsive ai costruttori. Quando crei un oggetto di classe C che deriva la classe B che deriva la classe A vengono richiamati i costruttori in maniera inversa (prima A, poi B, poi C ognuno dei quali stampa a video la scritta, nota che nel costruttore C c'è anche l'incremento delle variabili perciò stampa 4). La terza stampa era più difficile da intuire, come vedi nella classe C c'è la variabile A aa che viene istanziata prima della chiamata al costruttore (e non passando nessun parametro viene inizializzato il valore a con quello di default: 0 ) Da notare anche che A* pa = new C(3); dichiara il tipo di pa come A (classe madre) ma lo istanzia con new C(3) (classe figlia): questo è il polimorfismo.

l'istruzione:

Codice: Seleziona tutto

pa->f();
produce:

Codice: Seleziona tutto

C::f() b = 4
Semplice: il polimorfismo dice che viene richiamato il metodo della classe con cui è stata instanziato l'oggetto (classe figlia C) quindi stai richiamando C::F() e non il metodo della classe con cui è stato dichiarato l'oggetto (classe madre A). (La richiami con l'operatore -> in quanto pa è un puntatore)

l'istruzione:

Codice: Seleziona tutto

B* pb = new C(2);
produce:

Codice: Seleziona tutto

A : a = 2
B: b = 2
A : a = 0
C: a = 3
Stesso identico discorso della prima istruzione.

l'istruzione:

Codice: Seleziona tutto

pb->f();
produce:

Codice: Seleziona tutto

C::f() b = 3
Anche qui il polimorfismo fa in modo che venga chiamato il metodo della classe C anche se l'oggetto è dichiarato di tipo B.

l'istruzione:

Codice: Seleziona tutto

delete pa;
produce:

Codice: Seleziona tutto

via C
via A
via B
via A
Questo perché i distruttori vengono richiamati in maniera inversa ai costruttore. Per lo stesso discorso fatto nella discussione dei costruttori le stampe delle righe 1,3,4 sono intuitive (prima il distruttore di C elimina la parte propria di C, poi viene invocato il distruttore di B, poi il distruttore di A). La 2° riga invece indica la distruzione dell'attributo A aa della classe C (anche questo non è molto intuitivo)

l'istruzione:

Codice: Seleziona tutto

delete pb;
produce:

Codice: Seleziona tutto

via C
via A
via B
via A
stesso identico discorso di sopra.



Riflessioni totali:

1) mi hai permesso di ripetere un po' le classi in CPP, e per questo te ne sono grato  (b2b)
2) probabilmente avrei sbagliato solo la stampa di quella riga un po' antipatica creata dalla variabile aa della classe C (mettendola da qualche altra parte io avrei pensato sempre per ultimo)
3) se all'esame fai solo quell'errore lo passi di sicuro  ;)
4) Nota i metodi virtuali della classe A, significa che DEVONO essere assolutamente ridefiniti da una sottoclasse.

Spero ti abbia eliminato qualche dubbio.

In bocca al lupo per l'esame.
Ultima modifica di daemon_nio il sabato 6 settembre 2008, 23:40, modificato 1 volta in totale.
Sempre costruendo qualcosa di nuovo: Matag: The Game
Avatar utente
durzino
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 872
Iscrizione: mercoledì 5 luglio 2006, 21:14

Re: Classi c++

Messaggio da durzino »

Grazie sei stato molto utile ti volevo chiedere un ultima cosa,quando leggo accanto ad una funzione o accanto ad un distruttore la parola virtual mi devo comportare in maniera diversa? Guarda questo altro testo d'esame ,ti ringrazio per la grande disponibiltà http://www2.ing.unipi.it/~d8669/didatti ... 2-2006.pdf
...Meglio un terminale oggi Che un Crash oggi e domani...E dopodomani....
Avatar utente
daemon_nio
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1012
Iscrizione: lunedì 15 gennaio 2007, 14:18
Sesso: Maschile
Località: London
Contatti:

Re: Classi c++

Messaggio da daemon_nio »

A quanto ricordo se un metodo (o anche distruttore) viene dichiarato virtuale significa che quando lo ridefinisci lo sovraccarichi anche.

Se avessi avuto (mi riferisco all'esercizio 1):

Codice: Seleziona tutto

class A
  {...

   public:
      ...
      void stampa(){cout << "stampa A:" << x << endl;}
   };

class B: public A
  {...

    public:
       ...
       void stampa(){cout << "stampa B: " << x << endl;}
   };
invocando su un oggetto di tipo B la funzione stampa avresti avuto la doppia stampa (prima del metodo A::stampa() poi del metodo B::stampa() ).

Dichiarando invece virtuale il metodo stampa di A quando lo ridefinisci in B e lo richiami su di un oggetto di tipo B stai dicendo di voler eseguire solo B::stampa() senza eseguire prima A::stampa(). Quindi i metodi virtuali è come se non venissero ereditati.

Questo è quel che ricordo io... però ti conviene aspettare anche la conferma di qualcun altro o di dare uno sguardo a qualche testo.
Sempre costruendo qualcosa di nuovo: Matag: The Game
Avatar utente
durzino
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 872
Iscrizione: mercoledì 5 luglio 2006, 21:14

Re: Classi c++

Messaggio da durzino »

DAemon sei veraemnte molto disponibile,ho dato una letta ad un libro di testo poi ho provato a fare un nuovo esercizio,ho capito bene le chiamate dei costruttori ricorsive ma meno le chiamate di funzioni.. http://www2.ing.unipi.it/~d8669/didatti ... 9-2006.pdf
quando chiama pa->f() da a:f() x=7 ma perchè 7?
quando invece da pc->f() richiama normalmente la funzione f di della classe C.
...Meglio un terminale oggi Che un Crash oggi e domani...E dopodomani....
Dahman
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1013
Iscrizione: mercoledì 31 ottobre 2007, 8:29
Località: Torino

Re: Classi c++

Messaggio da Dahman »

quando chiama pa->f() da a:f() x=7 ma perchè 7?
perché in realtà ci sono due x:
quella dichiarata pubblica in A quindi visibile da tutte le classi
e quella dichiarata in C privata quindi visibile solo da C.
Inoltre la f() é virtual solo sotto B.
Una volta definito l'oggetto A *pa = new C, esso ha 2 x, quella privata che vale (sempre) 2 e quella pubblica che vale 7, passando per 5.
pa->f() esegue la funzione A::f() perché non virtual quindi restituisce l'unica x che A riesce a vedere, cioé 7. Ed ecco spiegato il risultato.

Spero di esserti utile

Ciao

Dahman
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 4 ospiti