Documente Academic
Documente Profesional
Documente Cultură
Prelegerea nr. 7:
Funcții virtuale și polimorfism
Silviu GÎNCU
Funcții virtuale și polimorfism
Sumar
1. Context
2. Polimorfism. Tipuri de polimorfism
3. Polimorfismul dinamic
4. Funcții virtuale pure. Clase abstracte
5. Destructori virtuali
6. Implementarea polimorfismului în C++
2
Se consideră următoarea ierarhie de clase
Persoana Student
Nume, prenume Nume, prenume, grupa
date Cod personalizat date Cod personalizat
Anul nașterii Anul nașterii
metode print metode print
Constructor cu parametri Constructor cu parametri
Student bursier
Nume, prenume, grupa
date Cod personalizat
Anul nașterii
bursa
metode print
Constructor cu parametri
Și apelul de în funcția principală
int main(){
persoana *a;
a=new persoana("Afanas", "Ion", 1990);
cout<<"Datele despre persoana"<<endl;
a->print();
delete a;
a=new st_bursier("Ciubotaru","Ana",2000,"SI-149",1000);
cout<<"\nDatele despre studentul bursier"<<endl;
a->print();
delete a;
}
Funcții virtuale
O funcţie virtuală este o funcţie membru care în clasa de bază
are specificat cuvântul cheie virtual, în clasele derivate cuvântul virtual
nu se utilizează:
class nume_baza{
//...
virtual tip_returnat nume_metoda();
...
};
class derivat : public nume_baza{
//...
tip_returnat nume_metoda();
...
};
În cazul funcțiilor virtuale, urmare a creării obiectelor claselor
derivate în baza unui pointer al clasei de bază, apelul funcțiilor derivate
se va efectua în corespundere cu constructorul în baza căruia acesta a
fost creat, adică se va apela funcția din clasa derivată
Pentru ierarhia de clase
persoana-student-st_bursier
class persoana{
// datele și metodele descrise anterior
virtual void print();
};
class student : public persoana{
// datele și metodele descrise anterior
void print();
};
class st_bursier : public student{
// datele și metodele descrise anterior
void print();
};
În acest caz, metoda print este virtuală pentru toate cele 3 clase
Apelul în funcția principală
int main(){
persoana *a; student *b;
a=new persoana("Afanas", "Ion", 1990);
a->print(); //virtual în acest caz nu are semnificație
delete a;
a=new student("Manole", "Maria", 1995, "TI-175");
a->print(); //din clasa de derivata student
delete a;
a=new st_bursier("Ciubotaru","Ana",2000,"SI-149",1000);
a->print(); //din clasa de derivata st_bursier
delete a;
b=new student("Manole", "Maria", 1995, "TI-175");
b->print(); //din clasa de derivata student
delete b;
b=new st_bursier("Ciubotaru","Ana",2000,"SI-149",1000);
b->print(); //din clasa de derivata st_bursier
delete b;
}
Concluzii
§ Cu ajutorul funcţiilor virtuale este posibilă proiectarea şi
implementarea sistemelor software care sunt mult mai uşor
extensibile
§ Programele pot fi concepute să proceseze în mod generic,
sub forma obiectelor din clasele de bază, a obiectelor
tuturor claselor dintr-o ierarhie
§ Clasele care nu există în timpul dezvoltării iniţiale a
programului pot fi adăugate ulterior cu modificări minore
sau chiar fără a face modificări părţii generice a
programului, atâta timp cât clasele sunt părţi ale ierarhiei
procesate generic
– Singurele părţi din program care trebuie modificate sunt cele care
folosesc informaţii specifice despre o clasă adăugată în ierarhie
Ce este polimorfismul?
Polimorfismul este capacitatea unor entități de a lua forme
diferite. Termenul provine de la:
polimorm Poly = multe + Morfm = forma
Este unul din conceptele esențiale din POO.
Tipuri de polimorfismul
Polimorfismul parametric – mecanismul prin care putem defini mai
multe metode cu același nume în aceeași clasă, dar să difere prin
numărul și/sau tipul parametrilor formali.
De exemplu: complex a, b, c; a=b+c; a=b+2.45;
Operaţia + se realizează între două obiecte de tip complex: b,
c şi dintre un obiect de tip complex şi o constată de tip număr real.
Afişează
Destructor derivat
Destructor baza Destructor baza
O aplicaţie a polimorfismului
O implementare a metodei reluării (tehnici de programare): algoritmul
este format dintr-o secvență unică de instrucțiuni cu același nume, dar
care se modifică diferit în dependenţă de problemă.
Schema generală a algoritmului recursiv
bazat pe metoda reluării
void reluare(int k){
if(k<=n) {
x[k]=PrimulElement(k);
if(Continuare(k)) reluare(k+1);
while(ExistaSuccesor(k)) {
x[k]=Succesor(k);
if(Continuare(k)) reluare(k+1);
}
}
else PrelucrareaSolutiei();
}
Implementare
Se va crea o clasă, în care funcțiile
init()
am_succesor()
e_valid()
solutie()
tipar()
să fie definite inițial cu valori simple, iar apoi în clasele derivate să
poată fi redefinite astfel încât să rezolve fiecare problemă în parte.
De aceea ele vor fi definite din start – în clasa de bază – ca fiind
virtuale, pentru ca apoi în clasele derivate să poată fi redefinite
corespunzător fiecărei clase în parte care rezolvă un anumit tip de
problemă.
Astfel, se va utiliza:
n - numărul de elemente; k - elementul curent;
as - are succesor (se mai poate adaugă un element pe nivelul curent)
ev - este valid (se îndeplinesc cerințele problemei).
Implementarea clasei de bază
class bkt{
protected:
int st[10],n,k;
public:
virtual void init() {}
virtual int am_succesor(){return 0;}
virtual int e_valid(){return 0;}
virtual int solutie(){return 0;}
virtual void tipar() {};
void run();
};
void bkt::run(){ int as; k=1; init();
while(k>0){
do{
}while((as=am_succesor())&&!e_valid());
if(as) if(solutie()) tipar();
else{ k++; init(); } else k--; }
}
Implementarea clasei permutări
class permut : public bkt{
public:
permut (int v) { n=v; }
void init();
int am_succesor();
int e_valid();
int solutie();
void tipar();
};
void permut::init(){ st[k]=0; }
int permut::am_succesor(){
if(st[k]<n){ st[k]++; return 1; } else return 0; }
int permut::e_valid(){
for(int i=1; i<k; i++) if( st[i] == st[k] ) return 0;
return 1;}
int permut::solutie(){return (k==n); }
void permut::tipar(){ for(int i=1;i<=k;i++)
cout<<st[i]<<" "; cout<<endl; }
Implementarea clasei regine
class dame : public permut{
public:
dame(int v) : permut(v) {};
int e_valid();
};
int dame::e_valid(){
for(int i=1; i<k; i++)
if((st[i]==st[k])||abs(st[k]-st[i])==abs(k-i)) return 0;
return 1;
}
main(){
cout<<"Permutari"<<endl;
permut x(3);
x.run();
cout<<"Plasarea reginelor"<<endl;
dame y(4);
y.run();
}
Interpretarea rezultatelor
1 2 3 4
1
2
3
4
Problemă
Organizarea problemei în clase / obiecte