Sunteți pe pagina 1din 11

Funcţii virtuale pure.

Clase abstracte 1

LUCRARE DE LABORATOR NR. 7

FUNCŢII VIRTUALE PURE. CLASE ABSTRACTE

I. Noţiuni teoretice

În cazul unei ierarhii de clase mai complicate, clasa de bază poate avea
nişte proprietăţi generale despre care ştim că există, dar nu le putem defini numai
în clasele derivate. În acest scop s-a introdus noţiunea de funcţie membră
virtuală pură.
Funcţia virtuală pură este o funcţie membră care este declarată, dar nu este
definită în clasa respectivă. Ea trebuie definită într-o clasă derivată. Funcţia
membră virtuală pură se declară în modul următor. Antetul obişnuit al funcţiei
este precedat de cuvântul cheie virtual şi acesta se termină cu „= 0”. După cum
arată numele şi declaraţia ei, funcţia membră virtuală pură este o funcţie virtuală
deci selectarea exemplarului funcţiei din ierarhia de clase se va face în timpul
executiei programului.
Clasele care conţin cel puţin o funcţie membră virtuală pură se vor numi
clase abstracte.
Deoarece clasele abstracte conţin funcţii membre care nu sunt definite, nu
se pot crea obiecte aparţinând claselor abstracte. Dacă funcţia membră virtuală
pură nu s-a definit în clasa derivată atunci şi clasa derivată va fi clasă abstractă şi
ca atare nu se pot defini obiecte aparţinând acelei clase.

II. Aplicaţii rezolvate

Aplicaţia 1
Să se definească clasa abstractă Magazin și clasele derivate Imbracaminte
si Laptop_IT. Să se implementeze funcții de acces la datele membre, respectiv
constructori pentru fiecare clasă. În funcția principală se vor instanția obiecte
pentru fiecare dintre clasele derivate.
- Magazin: tipul magazinului, nr de bucati produs
- Imbracaminte: categorie imbracaminte, marimea, nr de preturi si preturile
- Laptop_IT: categorie IT, capacitatea HDD, nr de preturi si preturile.
Implementati o functie virtuala pura, in clasa de baza, care sa determine în
clasa Imbracaminte prețul cel mai mare al unui produs, iar în clasa Laptop_IT
prețul cel mai mic al unui produs.

Programul corespunzător problemei este:


#include<iostream>
#include<conio.h>
2 Funcţii virtuale pure. Clase abstracte
#include<string.h>

using namespace std;

class Magazin
{protected:
char tip_magazin[20];
int nr_buc_produs;
public:
Magazin(){strcpy(tip_magazin,""); nr_buc_produs=0;};
Magazin(char* t,int nr);
Magazin(Magazin& m);
void afisare();
virtual double PretulCalculat()=0;
char* getTip_Magazin(){return tip_magazin;}
void setTip_Magazin(char* tip)
{strcpy(tip_magazin,tip);}
int getNrBuc_Produs(){return nr_buc_produs;}
void setNrBuc_Produs(int nr){nr_buc_produs=nr;}
};

Magazin::Magazin(char* t,int nr)


{strcpy(tip_magazin,t);
nr_buc_produs=nr;
}
Magazin::Magazin(Magazin& m)
{strcpy(tip_magazin,m.tip_magazin);
nr_buc_produs=m.nr_buc_produs;
}
void Magazin::afisare()
{
cout<<"\nTip magazin: "<<getTip_Magazin()<<" nr
bucati produs: "<<getNrBuc_Produs()<<" pretul
determinat: "<<PretulCalculat();
}

class Imbracaminte:public Magazin


{private:
char categorie_imbracaminte[20], marime[5];
int nr_preturi;
double pret[12];
public:

Imbracaminte():Magazin(){strcpy(categorie_imbracaminte,"
");strcpy(marime,""); nr_preturi=0; pret[0]=0;}
Funcţii virtuale pure. Clase abstracte 3
Imbracaminte(char *t, int n,char* c,char* m, int nr,
double* p);
Imbracaminte(Imbracaminte& i);
void afisareImbracaminte();
Imbracaminte atribuire(Imbracaminte &im);
virtual double PretulCalculat();
char* getCategorie_Imbracaminte(){return
categorie_imbracaminte;}
void setCategorie_Imbracaminte(char*
cat){strcpy(categorie_imbracaminte,cat);}
char* getMarime(){return marime;}
void setMarime(char* mar){strcpy(marime,mar);}
int getNrPreturi(){return nr_preturi;}
void setNrPreturi(int nr){nr_preturi=nr;}
double getPret(int i){return pret[i];}
void setPreturi(int nr){ nr_preturi=nr;
for (int i=0;i<nr;i++){cout<<"\nDati un pret:";
cin>>pret[i];}}
};

Imbracaminte::Imbracaminte(char *t, int n,char* c,char*


m, int nr, double* p):Magazin(t,n)
{ strcpy(categorie_imbracaminte,c);
strcpy(marime,m);
nr_preturi=nr;
for(int i=0;i<nr_preturi;i++)pret[i]=p[i];
}
Imbracaminte::Imbracaminte(Imbracaminte& im)
{ strcpy(tip_magazin,im.tip_magazin);
nr_buc_produs=im.nr_buc_produs;

strcpy(categorie_imbracaminte,im.categorie_imbracaminte)
;
strcpy(marime,im.marime);
nr_preturi=im.nr_preturi;
for(int i=0;i<nr_preturi;i++)pret[i]=im.pret[i];
}
void Imbracaminte::afisareImbracaminte()
{cout<<" Categorie imbracaminte:
"<<getCategorie_Imbracaminte()<<" marime:
"<<getMarime()<<" nr preturi: "<<getNrPreturi();
if(getNrPreturi()!=0){
cout<<"\nPreturile sunt: ";
for(int i=0;i<getNrPreturi();i++)cout<<"
"<<pret[i];}
}
4 Funcţii virtuale pure. Clase abstracte
double Imbracaminte::PretulCalculat()
{
double max=pret[0];
for(int
i=1;i<getNrPreturi();i++)if(max<pret[i])max=pret[i];
return max;
}

class Laptop_IT:public Magazin


{private:
char categorie_IT[20];
int capacitateHDD;
int nr_preturi;
double pret[12];
public:

Laptop_IT():Magazin(){strcpy(categorie_IT,"");capacitate
HDD=1024; nr_preturi=0; pret[0]=0;}
Laptop_IT(char *t, int n,char* c,int cap, int nr,
double* p);
Laptop_IT(Laptop_IT& l);
void afisareLaptop_IT();
Laptop_IT atribuire(Laptop_IT &l);
virtual double PretulCalculat();
char* getCategorie_IT(){return categorie_IT;}
void setCategorie_IT(char*
cat){strcpy(categorie_IT,cat);}
int getcapacitateHDD(){return capacitateHDD;}
void setcapacitateHDD(int cap){capacitateHDD=cap;}
int getNrPreturi(){return nr_preturi;}
void setNrPreturi(int nr){nr_preturi=nr;}
double getPret(int i){return pret[i];}
void setPreturi(int nr){ nr_preturi=nr;
for (int i=0;i<nr;i++){cout<<"\nDati un pret:";
cin>>pret[i];}}
};

Laptop_IT::Laptop_IT(char *t, int n,char* c,int cap, int


nr, double* p):Magazin(t,n)
{
strcpy(categorie_IT,c);
capacitateHDD=cap;
nr_preturi=nr;
for(int i=0;i<nr_preturi;i++)pret[i]=p[i];
}
Laptop_IT::Laptop_IT(Laptop_IT& l)
Funcţii virtuale pure. Clase abstracte 5
{ strcpy(tip_magazin,l.tip_magazin);
nr_buc_produs=l.nr_buc_produs;
strcpy(categorie_IT,l.categorie_IT);
capacitateHDD=l.capacitateHDD;
nr_preturi=l.nr_preturi;
for(int i=0;i<nr_preturi;i++)pret[i]=l.pret[i];
}
void Laptop_IT::afisareLaptop_IT()
{cout<<" Categorie IT:"<<getCategorie_IT()<<"
capacitate:"<<getcapacitateHDD()<<" nr
preturi:"<<getNrPreturi();
if(getNrPreturi()!=0){
cout<<"\nPreturile sunt: ";
for(int i=0;i<getNrPreturi();i++)cout<<"
"<<pret[i];}
}
double Laptop_IT::PretulCalculat()
{
double min=pret[0];
for(int
i=1;i<getNrPreturi();i++)if(min>pret[i])min=pret[i];
return min;
}
int main()
{ double preturi1[]={75,30,40};
Imbracaminte a("supermarket",12,"fuste","M",3,preturi1);
a.afisare();
a.afisareImbracaminte();

Imbracaminte a2(a);
a2.afisare();
a2.afisareImbracaminte();

double preturi2[]={200,190,195};
Laptop_IT l("supermarket",12,"laptop",1024,3,preturi2);
l.afisare();
l.afisareLaptop_IT();
return 0;
}
Aplicaţia 2
Să se definească clasa abstractă poliedru şi clasele derivate piramida şi
prisma, corespunzătoare noţiunilor de piramidă regulată, respectiv prismă
regulată.
Programul corespunzător problemei este:
#include <iostream>
#include <math.h>
6 Funcţii virtuale pure. Clase abstracte
using namespace std;
class poliedru {
protected:
float h;
public:
poliedru(float a=0){ h=a;}
virtual float aria_baza()=0;
virtual float aria_laterala()=0;
virtual float aria()=0;
virtual float volum()=0;
void afisare();
};
void poliedru::afisare()
{ cout.precision(2);
cout<<"\nAria bazei="<<aria_baza();
cout<<"\nAria laterala="<<aria_laterala();
cout<<"\nAria totala="<<aria();
cout<<"\nVolumul="<<volum()<<endl;
}
class piramida : public poliedru {
private:
float l;
int nr;
public:
piramida(){ l=0;h=0;nr=0;}
piramida(float l1, float h1, float nr1):
poliedru(h1){ l=l1;nr=nr1;}
piramida(piramida& );
float aria_baza();
float aria_laterala();
float aria()
{ return aria_baza()+aria_laterala();}
float volum();
};
piramida::piramida(piramida& p)
{
h=p.h;
l=p.l;
nr=p.nr;
}
float piramida::aria_baza()
{
return nr*l*l/(4*tan(3.14/nr));
}
float piramida::aria_laterala()
{
Funcţii virtuale pure. Clase abstracte 7
return nr*l/2*sqrt(h*h+l*l/(4*tan(3.1415/nr)));
}
float piramida::volum()
{
return aria_baza()*h/3;
}
class prisma : public poliedru {
private:
float l;
int nr;
public:
prisma(){ l=0;h=0;nr=0;}
prisma(float l1, float h1, float nr1):
poliedru(h1){ l=l1;nr=nr1;}
prisma(prisma& );
float aria_baza();
float aria_laterala();
float aria()
{ return 2*aria_baza()+aria_laterala();}
float volum();
};
prisma::prisma(prisma& p)
{
h=p.h;
l=p.l;
nr=p.nr;
}
float prisma::aria_baza()
{
return nr*l*l/(4*tan(3.14/nr));
}
float prisma::aria_laterala()
{
return nr*l*h;
}
float prisma::volum()
{
return aria_baza()*h;
}
int main()
{ piramida a(2,2,3);
cout<<"Tetraedrul regulat de latura 2";
a.afisare();
piramida b(2,2,4);
cout<<"\nPiramida patrulatera regulata ";
cout<<"cu latura bazei 2 si inaltime 2";
8 Funcţii virtuale pure. Clase abstracte
b.afisare();
prisma c(2,2,3);
cout<<"\nPrisma triunghiulara regulata ";
cout<<"cu latura bazei 2 si inaltime 2";
c.afisare();
prisma d(2,2,4);
cout<<"\nCubul de latura 2 ";
d.afisare();
return 0;
}

Programul afişează:
Tetraedrul regulat de latura 2
Aria bazei = 1.73
Aria laterala = 6.42
Aria totala = 8.15
Volumul = 1.16
Piramida patrulatera regulata cu latura bazei 2 si inaltime 2
Aria bazei = 4
Aria laterala = 8.94
Aria totala = 12.94
Volumul = 2.67
Prisma triunghiulara regulata cu latura bazei 2 si inaltime 2
Aria bazei = 1.73
Aria laterala = 12
Aria totala = 15.47
Volumul = 3.47
Cubul de latura 2
Aria bazei = 4
Aria laterala = 16
Aria totala = 24
Volumul = 8
Analiza programului:
Ierarhia de clase ce sunt implementate în acest program este prezentată în
figura 3. Declaraţia clasei de bază poliedru cuprinde o dată membră, declarată
protejată, şi şase funcţii membre, declarate publice.

Poliedru

Piramida Prisma

Figura 3. Ierarhie de clase


Funcţii virtuale pure. Clase abstracte 9
Data membră h, declarată de tip float, va preciza înălţimea unui poliedru.
Ea este declarată protejată pentru a putea fi accesată şi din funcţiile membre ale
claselor derivate din această clasă.
Toate funcţiile membre ale acestei clase sunt publice, deci pot fi accesate
din orice altă funcţie exterioară clasei. Patru dintre funcţiile membre: aria_baza,
aria_laterală, aria şi volum sunt declarate virtuale pure, ele caracterizând unele
proprietăţi ale obiectelor de tip poliedru ce nu pot fi definite. Deoarece clasa
poliedru conţine funcţii virtuale pure, ea este o clasă abstractă şi nu se vor putea
iniţializa obiecte de acest tip.
Prima funcţie definită la declaraţia clasei este constructorul ce permite
crearea unui poliedru a cărui înălţime este dată de parametrul constructorului. În
cazul în care nu se transmite un parametru actual, se va considera valoarea
implicită a parametrului formal.
Implementarea clasei poliedru constă din definirea funcţiei afisare. Această
funcţie nu primeşte parametri şi nu returnează date. În corpul acestei funcţii se
utilizează obiecte specifice operaţiei de ieşire pentru afişarea unor proprietăţi ale
obiectului ce a apelat funcţia.
Următoarea clasă definită este clasa piramida, aceasta moştenind în mod
public de la clasa poliedru. Sintaxa utilizată pentru definirea moştenirii este
următoarea:
class piramida : public poliedru
Pe lângă data membră moştenită din clasa de bază, această clasă mai are
două date membre:
 l - utilizată pentru memorarea lungimii laturii bazei;
 nr – utilizată pentru memorarea numărul de laturi ale bazei.
Toate funcţiile membre ale clasei sunt declarate publice. Constructorul
explicit al acestei clase va apela constructorul corespunzător al clasei de bază.
Cele patru funcţii virtuale pure moştenite de la clasa de bază se vor defini în
această clasă, deci clasa piramida nu este abstractă şi se vor putea instanţia
obiecte ale acestei clase. Funcţia membră aria se defineşte odată cu declararea
clasei prin apelul a două funcţii membre: aria_baza şi aria_laterala.
Implementarea clasei piramida constă din definirea a patru funcţii.
Constructorul de copiere se implementează pentru iniţializarea obiectelor
folosind un obiect de acelaşi tip, în acest caz tipul piramida.
Funcţia membră aria_baza nu primeşte parametri şi returnează o valoare de
tip float ce precizează aria bazei piramidei. Valoarea returnată se obţine prin
utilizarea unei formule care depinde de numărul de laturi şi de lungimea acestor
laturi egale.
Funcţia membră aria_laterala nu primeşte parametri şi returnează o valoare
de tip float ce precizează aria laterală a piramidei. Valoarea returnată se obţine
prin utilizarea unei formule care depinde de numărul de laturi, de lungimea
acestor laturi egale şi de înălţimea piramidei.
10 Funcţii virtuale pure. Clase abstracte
Funcţia membră volum nu primeşte parametri şi returnează o valoare de tip
float ce precizează volumul piramidei. Valoarea returnată se obţine prin
utilizarea unei formule care depinde de numărul de laturi, de lungimea acestor
laturi egale şi de înălţimea piramidei.
În continuare clasa definită este clasa prisma, aceasta moştenind în mod
public de la clasa poliedru. Sintaxa utilizată pentru definirea moştenirii este
următoarea:
class prisma : public poliedru
Pe lângă data membră moştenită din clasa de bază, această clasă mai are
două date membre:
 l - utilizată pentru memorarea lungimii laturii bazei;
 nr – utilizată pentru memorarea numărul de laturi ale bazei.
Toate funcţiile membre ale clasei sunt declarate publice. Constructorul
explicit al acestei clase va apela constructorul corespunzător al clasei de bază.
Cele patru funcţii virtuale pure moştenite de la clasa de bază se vor defini în
această clasă, deci clasa prisma nu este abstractă şi se vor putea instanţia obiecte
ale acestei clase. Funcţia membră aria se defineşte odată cu declararea clasei
prin apelul a două funcţii membre: aria_baza şi aria_laterala.
Implementarea clasei prisma constă din definirea a patru funcţii.
Constructorul de copiere se implementează pentru iniţializarea obiectelor
folosind un obiect de acelaşi tip, în acest caz tipul prisma.
Funcţia membră aria_baza nu primeşte parametri şi returnează o valoare de
tip float ce precizează aria bazei prismei. Valoarea returnată se obţine prin
utilizarea unei formule care depinde de numărul de laturi şi de lungimea acestor
laturi egale.
Funcţia membră aria_laterala nu primeşte parametri şi returnează o valoare
de tip float ce precizează aria laterală a prismei. Valoarea returnată se obţine prin
utilizarea unei formule care depinde de numărul de laturi, de lungimea acestor
laturi egale şi de înălţimea prismei.
Funcţia membră volum nu primeşte parametri şi returnează o valoare de tip
float ce precizează volumul prismei. Valoarea returnată se obţine prin utilizarea
unei formule care depinde de numărul de laturi, de lungimea acestor laturi egale
şi de înălţimea prismei.
În funcţia principală a programului se instanţiază obiecte ale claselor: piramida
şi prisma definite în acest program, aceste obiecte apelând funcţia membră
afisare care permite afişarea ariei şi volumului corespunzător obiectul.

III. Aplicaţii propuse

1. Copiați problema 1 și modificați aplicația astfel încât să permită


instanțierea a n obiecte de tip Imbracaminte, respectiv Laptop_IT. Creați
o funcție virtuala pentru determinarea preturilor totale pentru fiecare
produs (un produs are mai multe preturi).
Funcţii virtuale pure. Clase abstracte 11
2. Să se definească clasa abstractă poligon şi clasele derivate triunghi,
dreptunghi, pătrat şi hexagon regulat. Clasa abstractă va avea două
funcţii virtuale pure: perimetru şi aria.

3. Să se creeze următoarea ierarhie de clase utilizând conceptul de


moștenire. Accesul la datele membre se va face utilizând funcții de
acces. Clasele vor avea următoarele date membre:
- Echipament: producător
- Electrocasnic: tip (mare sau mic), garanție, categorie (frigider, etc), preț;
- Video: denumire, preț.

Echipament

Electrocasnic Video

În funcţia principală se vor instanţia n obiecte de tip


„TIP_ELECTROCASNIC” şi se vor afişa informaţiile despre acestea. Creați o
funcție virtuală care să determine cel mai mic preț.

4. Să se creeze următoarea ierarhie de clase utilizând conceptul de


compunere. Accesul la datele membre se va face utilizând funcții de
acces. Clasele vor avea următoarele date membre:
- Echipament: producător
- Electrocasnic: tip (mare sau mic), garanție, categorie (frigider, etc), preț;
- Video: denumire, preț.

Echipament

Electrocasnic Video

În funcţia principală se vor instanţia n obiecte de tip


„TIP_ELECTROCASNIC” şi se vor afişa informaţiile despre acestea. Creați o
funcție virtuală care să determine cel mai mare preț.

S-ar putea să vă placă și