feed
top
crea forum
cerca
feed
forum
supporto
discussione
cerca
È soltanto un
Pokémon con le armi
o è un qualcosa di più? Vieni a parlarne su
Award & Oscar!
JEHOVA e la NUOVA GERUSALEMME > INIZIO <
Blog libero tutti possono commentare nella zona chiacchiere tutti possono dire la sua , la CHAT è libera tutti possono usarla
Cerca
INDICE Appunti sulla programmazione C++
Accedi
11) Funzioni virtuali e polimorfismo funzioni di base virtual
Messaggi
OFF
LINE
JehovaZorobabele
Post: 257
Post: 246
Registrato il: 02/03/2016
Registrato il: 03/03/2016
Sesso: Maschile
0
0
03/08/2016
18:19
Polimorfismo, overloading, funzioni virtuali di base, puntatore della classe , biding
L’obbiettivo
del polimorfismo è di avere una funzione base e da questa base si deve ricavare
più funzioni da un’ unica base allo stesso modo non è l’overloadin che le
funzioni sono diverse e il compilatore sceglie una in base alla differenza , nel polimorfismo sono uguali virtuali e
gerarchiche il polimorfismo possiamo vederlo dietro un termosifone non ha
importanza il dietro se c’è una caldaia a gas oppure un camino o diversamente
una stufa a pellet rimane sempre un termosifone che riscalda una stanza e il
termosifone è l’ interfaccia un unico oggetto che è modificabile
Eravamo
rimasti con il rendere virtuali le classi ereditate per non aver la confusione
dentro il compilatore , invece ora possiamo operare diversamente per uguale scopo, rendere la funzione
dentro la classe base in modo virtuale e usare un puntatore della classe
per specificare quale funzione possiamo usare,
una funzione virtuale normalmente rimane come le normali funzioni , usando il polimorfismo si può accedere con un
puntatore di classe , per creare questo puntatore va creato dentro gli oggetti
della classe padre in modo che sia
riconosciuto dagli oggetti figli un esempio creiamo 3 classi una padre 2 classi figlie create dalla classe base tutte con la stessa funzione di nome solo la
funzione dentro la classe base è
dichiarata
virtual
nella creazione degli oggetti c’è il
puntatore
*p
è
creato con l’ oggetto della classe base vediamo :
#include<iostream> using namespace std;
class base{public:
virtual void func()
{ cout
<< " funzione di base \n"; }
};
class figlia1 : public base {public:
void func()
{ cout
<< " funzione di figlia1 \n"; }
};
class figlia2 : public base { public:
void func()
{ cout
<< " funzione di figlia2 \n"; }
};
int main() {
base b,
*p
; figlia1
f; figlia2 i;
p = &b;
p->func();
p = &f;
p->func();
p = &i;
p->func();
cout
<< "\n\n Per uscire premere un tasto + invio: "; char zx; cin >> zx; }
Il
puntatore
*p
legge dentro l’ indirizzo delle varie
classi
p= &
tramite l’ operatore
&
cosi trova le varie funzioni membro di ogni classe ,
utilizzando l’ operatore freccia
->
perché si usa il
puntatore, altrimenti per leggere i
membri delle classi si usava il
punto .
come si utilizza normalmente , comunque potevamo farlo
ugualmente chiamando con gli oggetti b.f.i. ognuno deve richiamare il suo membro b.func();
f.func(); i.func() e il programma va ugualmente
ma non sfrutta i vantaggi delle funzioni virtuali
Una
funzione virtuale può sembrare uguale alle funzioni usate per l’
oveloading invece no per 2 aspetti ,con
l’ overloadind, 2 funzioni uguali non possono essere uguali al limite deve
cambiare i parametri mentre le funzioni
virtuali devono essere proprio uguali poi special modo si deve copiare
fedelmente il prototipo specificato dentro la classe altrimenti il compilatore
non considera più funzioni virtuali ma funzioni per overloading , le funzioni virtuali non
possono essere static e friend e per
chiudere le funzioni costruttore non
possono essere virtuali mentre i distruttori si
Potevamo chiamare diversamente le
funzioni nel programma precedente
utilizzando anzi che i puntatori si
poteva utilizzare una funzione di chiamata tramite l’ indirizzo &, per la funzione virtuale vediamo un altro
programma rimane tutto come su eccetto per il puntatore , inoltre viene
inserita una nuova funzione (
void f
) che richiama la classe base inserisco solo la parte modificata :
void f
(base
&b) { b.funz();} int main () {
base ba; figlia1
f1; figlia2 f2;
f(ba); f(f1);
f(f2);
creazione degli oggetti ba
f1 f2
chiamata alle funzioni tramite
la funzione f con il richiamo
degli oggetti
ba f1 f2 le stesse funzioni uguali
funz
ereditate da base rimangono
ugualmente virtuali come è il prototipo
che è la prima dentro la funzione base,
se noi facciamo un cambio di
programma la figlia2 anzi che ereditare da base, eredita da figlia1, il
programma nei 2 modi d’esecuzione viene
sempre eseguito con lo stesso risultato
Quando
una funzione virtual non viene ridefinita nelle nuove versioni ereditate il compilatore utilizza la funzione di base ,oppure utilizza la funzione più
vicina secondo la gerarchia, siccome con
l’ eredità una classe nuova ereditata sono gerarchiche anche le funzioni
virtuali sono gerarchiche, pertanto se
una funzione virtuale non ridefinita ma solo chiamata il compilatore utilizzerà la funzione più
vicina alla chiamata, nel caso nostro se
figlia2 è derivata dalla classe
base usa funz di base, se invece è
derivata da figlia1 usa la funzione di figlia1 ma se entrambe deriva
dalla base si usa quella più vicina ridefinita nostro caso è figlia1
Possiamo
avere 3 diverse funzione ma legate dallo stesso nome come ad esempio leggi() ,
e questo deve leggere delle condizioni differenti ma stesso tempo uguali,
allora cosi si crea nella classe base una funzione virtuale pura che grosso
modo è la base per le altre funzioni che avranno la stessa mansione per creare
una
funzione pura virtuale
virtual
tipo nome_funzione (parametri)=0;
Ora
ogni classe derivata deve avere la stessa funzione con una propria definizione
un esempio facciamo 4 funzioni dove si calcola diversamente 2 numeri e li si legge con un’ unica interfaccia
abbiamo 4 operazioni diverse l’ interfaccia
è sempre
virtual void leggi (int a,int b)
=0 ;
ecco il programma scritto con 4 classi diverse ma tutte usano la
funzione
void leggi(int a,
int b)
che è l’ interfaccia base :
#include<iostream> using namespace std;
class
base{ public:
virtual void leggi(int a, int b) = 0;
};
class
somma : public base{ public:
void leggi(int a , int b)
{cout << a + b <<" : = 30 +
2 \n";} };
class
sottrazione :public base{ public:
void leggi(int a , int b
){cout << a - b << " : = 30 - 2
\n";} };
class
moltiplica :public base{ public:
void leggi(int a , int b)
{cout << a * b << " : = 30 * 2 \n";}};
class
dividi :public base{public:
void leggi(int a , int b)
{cout << a / b
<<" : = 30 / 2 \n"; } };
int
main () {
somma s; sottrazione
o; moltiplica
m; dividi d;
s.leggi(30 , 2); o.leggi(30 ,
2); m.leggi(30
, 2); d.leggi(30
, 2);
cout << "\n\n premere un tasto +
invio per uscire: "; char zx; cin >> zx; }
Con gli
oggetti s, o, m, d
siamo andati a leggere dentro le varie
funzioni leggi , se nella funzione virtuale pura togliamo un parametro
int b
ecco che il compilatore
non compila più e da errore, il che si presume che la base del programma sia
proprio (
virtual void
leggi(int a, int b) = 0;
) infatti questa è l’ interfaccia comune per
tutte e 4 funzioni delle 4 classi derivate, una volta che si usa una
funzione virtuale pura
tutte le classi derivate deve avere
necessariamente la stessa funzione
ridefinita caso contrario il compilatore protesta qui non abbiamo usato l’
overloading
ma il
polimorfismo
abbiamo usato 4
funzioni [
void leggi(int
a,int b)
] la classe base che abbiamo usato per inserire la
funzione virtuale pura
si
chiama
classe astratta
e qui non serve la creazioni di alcun oggetto come avete visto dentro non c’è
nessun oggetto nella classe base, esiste solo il prototipo delle funzione
virtuale [ leggi() ], ma nella classe
base possiamo usare sempre i puntatori alla suddetta classe base
base b ,*p
cosi per accedere usiamo l’ operatore
freccia
->
come visto nei precedenti esempi la funzione virtuale è una
interfaccia primaria dove si costruisce
un esempio di base per poi creare più tipi diversi meglio specificati nelle
classi figlie, un esempio desideriamo
conoscere la differenza tra litro e centilitri
è uguale come la differenza tra
chilo e quintale oppure tra un metro e un chilometro o tra un metro è i pollici l’ interfaccia
rimane sempre la stessa anche se poi alla fine i dati sono diversi, la
funzione virtuale
crea questo tipo di base che poi nelle nuove
funzioni saranno implementate secondo
quello che ci serve nel dettaglio in questo modo si crea 2 sistemi di
rilegatura definito in inglese il
binding anticipato
e ritardato nella legatura ritardata fa parte quella
porzione di programma che non si conosce finché non viene avviato il
programma un esempio un puntatore va e
legge nella casella di memoria x, ma
finché in x non è scritto nulla non si sa che cosa ci sia dentro la particella
di memoria, mentre il
biding ritardato
è
quando usiamo una domanda e dobbiamo inserire i dati con il cin >> in poche parole il
binding ritardato
è tutto quello che il
compilatore non conosce prima di compilare il programma , all’ inverso il binding anticipato è
tutto quello che il compilatore riconosce fin da subito se noi scriviamo una
classe una variabile ecc… già il compilatore conosce queste cose visto che le
possiamo leggere con l’ aiuto dell’ intellisense quello è tutte quelle funzioni operazioni
anticipate fin da prima di avviare il compilatore
Ciao
grazie da ByMpt-Zorobabele
Testo PDF aggiornato con questo ultimo capitolo inserito lo trovate
:
http://www.freeforumzone.com/d/11266858/Elenco-figure-dei-comandi-della-programmazione-C-TESTO-PDF/discussione.aspx
Anche qui di queste discussioni che inserisco faccio un testo PDF da poter
scaricare tutto il mio
materiale è da utilizzare come desiderate per il testo PDF vedi cartella
dedicata , ogni volta cambia ubicazione del testo allora cambio il file e
il testo lo inserisco dentro la cartella < file aggiornato ad oggi >
http://www.freeforumzone.com/d/11266858/Elenco-figure-dei-comandi-della-programmazione-C-TESTO-PDF/discussione.aspx
Visualizza l'intera discussione
1
5
MediaObject
2,00
40
1
Tag discussione
polimorfismo
bympt-zorobabele
programmare cpp
overloading
virtual
biding anticipato
binding ritardato
Registrati
Accedi
INDICE Appunti sulla programmazione C++
Accedi
IL MIO PROFILO
LE MIE DISCUSSIONI
FORUM CHE SEGUI
LA MIA FORUM-CARD
MODIFICA FORUM-CARD
FAQ
TRADUCI
LOGOUT
Accedi
Registrati
FAQ
TRADUCI
Scatta o carica foto
Allega file
Inserisci link da url (card)
Incorpora url (YouTube/Twitter/...)
ACCETTA
RIFIUTA
Anteprima