Ecco la funzione virtuale!
Mi sono chiesto "ma perché bisogna ripetere ogni volta il codice del metodo, se il nome del metodo è uguale, nella dichiarazione delle diverse classi derivate?
E ho trovato le funzioni virtuali: mettere nella dichiarazione della classe base il metodo come virtuale per poi ridefinire il metodo nella dichiarazione delle classi derivate.
Ma, ripensandoci bene, dov'è il vantaggio, se bisogna comunque riscrivere sempre il codice del metodo nella dichiarazione della classe derivata, da sostituire alla dichiarazione della funzione virtuale?
La differenza sta nel fatto che si può usare un puntatore del tipo della classe base per ogni classe derivata, e tramite il puntatore si può fare riferimento alla funzione virtuale, ma solo se questa è dichiarata nella classe base.
#include "iostream"
using namespace std;
class Poligono{
protected:
int base,altezza;
public:
virtual int area(){
return 0;
}
};
class Rettangolo:public Poligono{
public:
Rettangolo(int b,int a){
base=b;
altezza=a;
}
int area(){
return base*altezza;
}
};
class Triangolo:public Poligono{
public:
Triangolo(int b, int a){
base=b;
altezza=a;
}
int area(){
return base*altezza/2;
}
};
void main(){
Rettangolo mioRettangolo(3,4);
Triangolo mioTriangolo(3,4);
Poligono * figura1 = &mioRettangolo;
Poligono * figura2 = &mioTriangolo;
cout << figura1->area() <<endl;
cout << figura2->area() << endl;
getchar();
}
Ma ora ho un dubbio: se la funzione, il metodo, non fosse dichiarato
virtual non sarebbe la stessa cosa?
Proviamo subito a dichiarare il metodo non virtuale. Anche i metodi non virtuali possono essere ridefiniti nelle classi derivate, dunque che differenza c'è?
#include "iostream"
using namespace std;
class Poligono{
protected:
int base,altezza;
public:
int area(){
return 0;
}
};
class Rettangolo:public Poligono{
public:
Rettangolo(int b,int a){
base=b;
altezza=a;
}
int area(){
return base*altezza;
}
};
class Triangolo:public Poligono{
public:
Triangolo(int b, int a){
base=b;
altezza=a;
}
int area(){
return base*altezza/2;
}
};
void main(){
Rettangolo mioRettangolo(3,4);
Triangolo mioTriangolo(3,4);
Poligono * figura1 = &mioRettangolo;
Poligono * figura2 = &mioTriangolo;
cout << figura1->area() <<endl;
cout << figura2->area() << endl;
getchar();
}
E vediamo l'output:
0
0
Ecco: invece, rendendo di nuovo la funzione virtuale:
#include "iostream"
using namespace std;
class Poligono{
protected:
int base,altezza;
public:
virtual int area(){
return 0;
}
};
class Rettangolo:public Poligono{
public:
Rettangolo(int b,int a){
base=b;
altezza=a;
}
int area(){
return base*altezza;
}
};
class Triangolo:public Poligono{
public:
Triangolo(int b, int a){
base=b;
altezza=a;
}
int area(){
return base*altezza/2;
}
};
void main(){
Rettangolo mioRettangolo(3,4);
Triangolo mioTriangolo(3,4);
Poligono * figura1 = &mioRettangolo;
Poligono * figura2 = &mioTriangolo;
cout << figura1->area() <<endl;
cout << figura2->area() << endl;
getchar();
}
12
6
Se la funzione non è virtuale, il puntatore fa riferimento alla funzione della classe base, che restituisce zero. Se la funzione della classe base è virtuale, invece, fa riferimento alla funzione della classe derivata.