Mostenire clase de baza clase derivate
Informatica :: IT :: C++
Pagina 1 din 1
Mostenire clase de baza clase derivate
• Una dintre caracteristicile programarii orientate pe obiecte, incapsularea, face posibila aplicarea mecanismului de mostenire. Mostenirea consta in preluarea atributelor de la o clasa numita clasa de baza, la o alta clasa numita clasa derivata. Ca atare, clasele derivate poseda toate caracteristicile clasei de baza, care pot fi imbunatatite atat functional, cat si structural.
• O reprezentare a claselor sub aspectul mostenirii conduce la o ierarhizare, adica o dispunere pe anumite nivele a acestora.
• Mostenirea poate fi simpla sau multipla, dupa cum clasa derivata mosteneste caracteristicile de la o clasa de baza sau de la mai multe clase de baza.
• Derivarea claselor, in functie de solicitari, reprezinta un proces cu durata variabila, de aceea se recomanda conceperea unor clase de baza cat mai simple.
• Procesul de mostenire ofera o serie de avantaje care constau in:
a) posibilitatea utilizarii unui cod comun pentru mai multe clase;
b) obtinerea extensiei unei clase fara a fi necesara o recompilare a clasei initiale;
c) sansa functiilor, care folosesc obiecte din clasa de baza, de a dispune si de obiecte dintr-o clasa derivata a sa.
d) utilizarea polimorfismului in timpul executiei programului prin folosirea functiilor virtuale [L9] etc.
• Reutilizarea codului este posibila in programarea orientata pe obiecte, sub doua aspecte:
1) prin compunere - includerea de obiecte in cadrul altor obiecte;
2) prin mostenire - crearea unor obiecte folosind o colectie de obiecte existente la un moment dat.
• Prin compunere, obiectul, care include un alt obiect, va avea ca elemente membre, toate elementele membre ale obiectului inclus, alaturi de cele specifice lui. Accesul la membrii obiectului inclus se va realiza prin intermediul acestui obiect.
Exemplu:
# include<iostream.h>
class punct
{
public:
float u,v;
void pp(float a, float b){u=a; v=b;}
};
class cerc
{
public:
punct O;
float r;
void dr(float raza){r=raza;}
};
void main( )
{
punct O;
O.u=7.9;
cerc c;
c.dr(12); // c.r=12
c.O.pp(7.5,10.5); // c.O.a=7.5 , c.O.b=10.5
}
• Operatia de derivare obtinuta prin procesul de mostenire constituie o varianta mult imbunatatita de reutilizare a codului.
Sintaxa:
class iden_clasa_derivata: specificator_acces iden_clasa_baza
{
// corpul clasei derivate
}
• Accesul la membrii din interiorul clasei derivate este determinat de specificatorul de acces. Accesul in clasa de baza poate fi public, private sau protected. Daca o clasa derivata este de tip class si nu se precizeaza specificatorul de acces, atunci implicit va fi private, iar in cazul clasei derivate de tip struct, va fi public.
• Drepturile de acces ale clasei derivate asupra membrilor clasei de baza:
• In general, protected nu este folosit ca specificator de acces in procesul de mostenire. Rolul sau este de a permite accesarea unor membri care nu fac parte din sectiunea public a clasei de baza, in clasa derivata.
• Indiferent de specificatorul de acces (public sau private) folosit, membrii din sectiunea private a clasei de baza nu pot fi direct accesati in clasa derivata. Accesarea lor se face prin functiile membre mostenite de la clasa de baza.
• Folosind specificatorul de acces public, se mai spune, ca transformam clasa de baza intr-o clasa publica. Membrii protejati (protected) din clasa de baza raman protejati si in clasa derivata.
• Daca se utilizeaza specificatorul de acces private, clasa de baza devine privata si toti membrii declarati public in ea devin privati in clasa derivata. Membrii protejati din clasa de baza devin privati in clasa derivata.
• Clasele derivate sunt tratate ca subclase ale clasei de baza, obiectele derivate pot fi atribuite obiectelor clasei de baza, fara a fi necesara conversia de tip. #n astfel de atribuiri se vor copia numai membrii clasei de baza. Astfel de atribuiri nu se pot realiza decat cu obiecte bazate pe relatia de mostenire.
Exemplu:
# include <iostream.h>
class B // def.clasei de baza B
{
int k,l;
public:
void punct(int a,int b){k=a; l=b;}
void afis( ){cout<<k<<" "<<l<<"\n";} };
class D:public B // def. clasei derivate D
{
int u;
public:
D(int w){u=w;}
void afis_1( ){cout<<u<<"\n";}
};
main( )
{
D ob(5);
ob.punct(6,9); // acces la un membru al clasei de baza B
ob.afis( ); // acces la un membru al clasei de baza B
ob.afis_1( ); // acces la un membru al clasei derivate D
return 0;
}
Exemplu:
#include<iostream.h> #include<conio.h> #include<math.h> #include<string.h> class baza
{ protected: int x; int y; public: baza(int xi=1,int yi=2)
{
x=xi;
y=yi;
}
float r_x(){return x;}
float r_y(){return y;}
};
class derivata:public baza
{
protected:
int k,l;
public:
derivata(int q=5,int p=3):baza(q,p)
{k=q;l=p;}
};
float ad_1(baza b,derivata d)
{
float f;
f=b.r_x()+d.r_x();
return f;
}
float ad_2(baza b,derivata d)
{
float f_1;
f_1=b.r_y()+d.r_y();
return f_1;
}
float dif_1(baza b,derivata d)
{
float f_2;
f_2=b.r_x()-d.r_x();
return f_2;
}
float dif_2(baza b,derivata d)
{
float f_3;
f_3=b.r_y()-d.r_y();
return f_3;
}
void main()
{
float u_1,u_2,u_3,u_4;
clrscr();
baza b;
derivata d;
float f1,f2,f3,f4,f5;
cout<<"\n";
u_1=b.r_x();
cout<<u_1;
cout<<"\n";
u_2=b.r_y();
cout<<u_2;
u_3=d.r_x();
cout<<"\n"<<u_3;
u_4=d.r_y();
cout<<"\n"<<u_4;
cout<<"\n";
f1=ad_1(b,d);
cout<<"\n"<<f1;
f2=ad_2(b,d);
cout<<"\n"<<f2;
f3=dif_1(b,d);
cout<<"\n"<<f3;
f4=dif_2(b,d);
cout<<"\n"<<f4;
cout<<"Lungimea segmentului:";
f5=sqrt(f4*f4+f3*f3);
cout<<"\n"<<f5;
derivata t(f1,f2);
f3=dif_1(b,t);
cout<<"\n f3="<<f3;
f4=dif_2(b,t);
cout<<"\n f4="<<f4;
cout<<"\n Lungimea noului”; cout<<”segment:"<<sqrt(f3*f3+f4*f4);
}
Se observa ca specificatorul de acces fiind public (mostenire publica), obiectele de tip derivat (din clasa derivata) pot accesa direct membrii publici din clasa de baza.
• Nu este permisa transformarea unui membru private al clasei de baza intr-un membru public sau protected al clasei derivate.
Conversia de tipul (C_D*)->(C_B*) se poate realiza:
a) implicit, daca specificatorul de acces este public;
b) explicit, cu operatorul cast, daca specificatorul de acces este private.
Conversia de tipul (C_B*)->(C_D*) se poate realiza doar explicit cu operatorul cast.
Aceste conversii, in procesul de mostenire, trebuie facute cu multa atentie, la nivel de pointeri, pentru ca pot conduce la erori greu de detectat. Pentru detalii vezi aI.Muslea – C++.....s.
• Specificatorul protected asigura o flexibilitate a mecanismului de mostenire. De regula, un membru al unei clase declarat protected nu este accesibil decat membrilor clasei respective. Accesul la un membru protejat este acelasi cu accesul la un membru privat cu o singura exceptie, si anume, membru protejat poate fi mostenit.
Exemplu:
# include<iostream.h>
class B
{
protected:
int u,v;
// sunt membrii particulari pentru clasa B, dar accesibili pentru clasa derivata D
public:
void punct(int a, int b){u=a; v=b;}
void afis( ){cout<<u<<" "<<v<<"\n";}
};
class D: public B
{
int w;
public:
void expr( ){w=u+v;} // este permis accesul in D la membrii protected u si v din B
void afis_1( ){cout<<w<<"\n";}
};
main( )
{
D ob;
ob.punct(6,9); // este corect pentru D
ob.afis( ); // idem
ob.expr( );
ob.afis_1( );
return 0;
}
Daca membrii u si v ar fi fost declarati in clasa B private, atunci in D nu s-ar fi permis acces la ei si programul nu s-ar putea compila.
• Daca, totusi, se mosteneste o clasa de baza cu protected, atunci membrii publici si protejati ai clasei de baza devin membrii protejati ai clasei derivate.
Exemplu:
# include <iostream.h>
class B
{
protected:
int u,v;
// membrii protejati pentru clasa B, accesibili pentru clasa derivata D
public:
void punct(int a, int b){ u=a; v=b;}
void afis(){cout<<u<<" "<<v<<"\n";}
};
class D:protected B
{
int w;
public:
void expr( ){punct(9,11); w=u+v;}
void afis_1( ){cout<<w<<" "; afis( );}
};
main( )
{
D ob;
ob.expr ( ); // corect - este membru public din clasa D
ob. afis_1( ); // idem
return 0;
}
Incorect ar fi:
ob.punct(6,9);
ob.afis( );
pentru ca s-ar folosi membrii protejati ai clasei D, desi sunt declarati publici in clasa B.
• Daca o clasa derivata va deveni o clasa de baza pentru o noua clasa derivata, atunci orice membru protejat al clasei de baza initiale (clasa mostenita cu public de catre prima clasa derivata), poate fi mostenit ca protected de a doua clasa derivata.
Exemplu:
# include <iostream.h>
class B
{
protected:
int u,v;
public:
void punct(int a, int b){u=a;v=b;}
void afis( ){cout<<u<<" "<<v<<"\n";}
} ;
class D_1:public B
{ //u si v sunt mosteni\i direct ca protected din B
int w;
public:
void expr( ){w=u+v;}// acces corect la u si v
void afis_1( ){cout<<w<<"\n";}
};
class D_2:public D_1
{ // clasa derivata D_2 are clasa de baza D_1
int k;
public:
void expr_k( ){k=u*v;}
// u si v sunt mosteniti indirect prin clasa D_1. Acces corect
void afis_k( ){cout<<k<<"\n";}
};
main( )
{
D_1 ob_1;
D_2 ob_2;
ob_1.punct(6,9);
ob_1.afis( );
ob_1.expr( );
ob_1.afis_1( );
ob_2.punct(5,;
ob_2.afis( );
ob_2.expr_1 ( );
ob_2.expr_k( );
ob_2.afis_1( );
ob_2.afis_k( );
return 0;
}
Daca clasa B ar fi mostenita cu specificatorul private, atunci toti membrii din B ar deveni membri private in clasa D_1, ceea ce inseamna ca ei nu vor fi accesibili lui D_2. Totusi, u si v (protected in B) continua sa ramana accesibili lui D_1.
• Ca o concluzie, daca clasa de baza B este mostenita cu specificatorul de acces private in clasa derivata D_1, clasa D_1 continua sa aiba acces la membrii declarati public si protected din clasa B. Aceasta proprietate nu se mai poate transmite in continuare.
• Intr-o mostenire pot fi folosite mai multe clase de baza (mostenire multipla).
Exemplu:
# include <iostream.h>
class B_1
{
protected:
int k;
public;
void afis_1( ){cout<<k<<"\n";}
};
class B_2
{
protected:
int u:
public:
void afis_2( ){cout<<u<<"\n";}};
class D:public B_1,public B_2
{ // mostenire din doua clase de baza B_1,B_2
public:
void punct(int a, int b){k=a; u=b;
};
main( )
{
D ob;
ob.punct(9,3); //corect prin clasa D
ob.afis_1( ); // corect din clasa B_1
ob.afis_2( ); // corect din clasa B_2
return 0;
}
Se observa ca trebuie mentionat specificatorul de acces la fiecare clasa de baza mostenita.
• Orice functie, care opereaza cu un obiect din clasa de baza, va putea opera si asupra unui obiect din clasa derivata, deoarece clasa derivata include tot ceea ce contine clasa de baza, fara a recompila codul initial al functiei. De aceea este necesar a vedea modul de organizare al fisierelor intr-o astfel de ierarhie.
Exemplu:
#include<iostream.h>
#define PI 3.141;
class Punct
{
public:
float x,y;
void O(float x0,float y0){x=x0;y=y0;}
void afis()
{
cout<<"X="<<x;cout<<"\n";
cout<<"Y="<<y;
cout<<"\n";
}
};
class Cerc:public Punct
{
public:
float raza,A;
void R(float r){raza=r;}
float aria(){A=PI*raza*raza;return A;}
void afis(){cout<<"RAZA="<<raza;cout<<"\n";
cout<<"Aria="<<A;}
};
void main()
{
Punct p;
p.O(2.5,-5.;
p.afis();
Cerc c;
c.R(10.);
c.aria();
c.afis();
}
Analizati acest exemplu si precizati principalele sale caracteristici.
Aplicatie:
Sa se implementeze clasele "carte", "stare", "cititor", "fisa", cu scopul realizarii unei evidente cu privire la posibilitatea de a imprumuta o carte de la biblioteca. Se au in vedere urmatoarele conditii:
- cititorul poate imprumuta o singura carte;
- fiecare carte este unica in biblioteca;
- imprumutul depinde de existenta cartii respective in biblioteca (daca nu este deja imprumutata).
#include<iostream.h> #include<conio.h> typedef enum {impr,ret}mod_i; typedef enum{lib,ocup}stare;
class nod
{
public:
char*autor;
char*titlu;
char*data_i;
char*data_r;
};
int i=0,j=0;
char data[8];
class carte
{
public:
char*autor;
char*titlu;
stare stare_carte;
void act_stare(stare);
void afisare();
carte();
};
class cititor
{
protected:
char*nume;
char*adresa;
int legit;
public:
int informare(carte&);
void solicitare(carte&);
void returnare(carte&);
cititor();
};
class fisa:public cititor
{
nod carti[10];
int nr_crt;
// prima intrare libera in fisa
public:
void imprumut(mod_i,carte&);
void actualizare(mod_i,carte);
void afis_inr(int i);
fisa(){nr_crt=0;}
};
void fisa::imprumut(mod_i tip_i,carte& cartea)
{
if(tip_i==impr)
{cout<<"cititorul"<<nume<<"solicita cartea";
cout<<"\n";
cout<<cartea.titlu<<""<<"autor"<<cartea.autor;
cout<<"\n";
if(!informare(cartea)){
cout<<"cartea solicit. este imprumutata:"; cout<<"\n";} else
{ solicitare(cartea);
actualizare(tip_i,cartea);
cartea.act_stare(ocup);
}
}
if(tip_i==ret)
{
cout<<"cititorul"<<nume<<"returneaza cartea";
cout<<"\n";
cout<<cartea.titlu<<" "<<"autorul:"<<cartea.autor; cout<<"\n";
returnare(cartea);
actualizare(tip_i,cartea);
cartea.act_stare(lib);
}
}
void fisa::actualizare(mod_i tip_i,carte cartea)
{
if(tip_i==impr)
{
nr_crt++;
carti[nr_crt].titlu=new char[10];
carti[nr_crt].titlu=cartea.titlu;
carti[nr_crt].autor=new char[20];
carti[nr_crt].titlu=cartea.autor;
carti[nr_crt].data_i=new char[8];
carti[nr_crt].data_i=data;
cout<<"data imprumutului";cout<<"\n";
cin>>data;
}
if(tip_i==ret)
{
cout<<"data returnarii";
cout<<"\n";
cin>>data;
carti[nr_crt].data_r=new char[8];
carti[nr_crt].data_r=data;
}
}
void fisa::afis_inr(int i)
{
cout<<"titlu;"<<carti[i].titlu;
cout<<"\n";
cout<<"autor:"<<carti[i].autor;
cout<<"\n";
cout<<"imprumutata data:"<<carti[i].data_i;
cout<<"\n";
cout<<"returnata data:"<<carti[i].data_r;
cout<<"\n";
}
carte::carte()
{
j++;
cout<<"date asupra cartii:"<<j;
cout<<"\n";
titlu=new char[11];
cout<<"titlul cartii:\n";
cout<<"\n";
cin>>titlu;
autor=new char[20];
cout<<"\n";
cout<<"autor\n";
cin>>autor;
stare_carte=lib;
}
void carte::act_stare(stare st){stare_carte=st;}
void carte::afisare()
{
cout<<"den.carte\n"<<titlu;
cout<<"\n";
cout<<"autor\n"<<autor;
cout<<"\n";
}
int cititor::informare(carte& cartea)
{
if(cartea.stare_carte==lib)return 1; if(cartea.stare_carte==ocup)return 0;
return 1;
}
void cititor::solicitare(carte& cartea)
{cartea.act_stare(ocup);}
void cititor::returnare(carte& cartea)
{cartea.act_stare(lib);}
cititor::cititor()
{
i++;
cout<<"datele pentru fisa"<<i<<"\n";
cout<<"nume\n";
nume=new char[10];
cin>>nume;
cout<<"\n";
cout<<"adresa\n";
adresa=new char[20];
cin>>adresa;
cout<<"\n";
cout<<"legit\n";
cin>>legit;
cout<<"\n";
}
void main()
{
clrscr();
fisa tf[2];
carte tc[2];
tf[0].imprumut(impr,tc[0]);
tf[1].imprumut(impr,tc[0]);
tf[0].imprumut(ret,tc[1]);
tf[1].imprumut(impr,tc[1]);
getch();
}
• O reprezentare a claselor sub aspectul mostenirii conduce la o ierarhizare, adica o dispunere pe anumite nivele a acestora.
• Mostenirea poate fi simpla sau multipla, dupa cum clasa derivata mosteneste caracteristicile de la o clasa de baza sau de la mai multe clase de baza.
• Derivarea claselor, in functie de solicitari, reprezinta un proces cu durata variabila, de aceea se recomanda conceperea unor clase de baza cat mai simple.
• Procesul de mostenire ofera o serie de avantaje care constau in:
a) posibilitatea utilizarii unui cod comun pentru mai multe clase;
b) obtinerea extensiei unei clase fara a fi necesara o recompilare a clasei initiale;
c) sansa functiilor, care folosesc obiecte din clasa de baza, de a dispune si de obiecte dintr-o clasa derivata a sa.
d) utilizarea polimorfismului in timpul executiei programului prin folosirea functiilor virtuale [L9] etc.
• Reutilizarea codului este posibila in programarea orientata pe obiecte, sub doua aspecte:
1) prin compunere - includerea de obiecte in cadrul altor obiecte;
2) prin mostenire - crearea unor obiecte folosind o colectie de obiecte existente la un moment dat.
• Prin compunere, obiectul, care include un alt obiect, va avea ca elemente membre, toate elementele membre ale obiectului inclus, alaturi de cele specifice lui. Accesul la membrii obiectului inclus se va realiza prin intermediul acestui obiect.
Exemplu:
# include<iostream.h>
class punct
{
public:
float u,v;
void pp(float a, float b){u=a; v=b;}
};
class cerc
{
public:
punct O;
float r;
void dr(float raza){r=raza;}
};
void main( )
{
punct O;
O.u=7.9;
cerc c;
c.dr(12); // c.r=12
c.O.pp(7.5,10.5); // c.O.a=7.5 , c.O.b=10.5
}
• Operatia de derivare obtinuta prin procesul de mostenire constituie o varianta mult imbunatatita de reutilizare a codului.
Sintaxa:
class iden_clasa_derivata: specificator_acces iden_clasa_baza
{
// corpul clasei derivate
}
• Accesul la membrii din interiorul clasei derivate este determinat de specificatorul de acces. Accesul in clasa de baza poate fi public, private sau protected. Daca o clasa derivata este de tip class si nu se precizeaza specificatorul de acces, atunci implicit va fi private, iar in cazul clasei derivate de tip struct, va fi public.
• Drepturile de acces ale clasei derivate asupra membrilor clasei de baza:
Drept de acces in clasa de baza | Specificator de acces sau modificatorul de protectie din lista claselor de baza | Drept de acces in clasa derivata |
PUBLIC PRIVATE PROTECTED | PUBLIC PUBLIC PUBLIC | PUBLIC inaccesibil PROTECTED |
PUBLIC PRIVATE PROTECTED | PRIVATE PRIVATE PRIVATE | PRIVATE inaccesibil PRIVATE |
• Indiferent de specificatorul de acces (public sau private) folosit, membrii din sectiunea private a clasei de baza nu pot fi direct accesati in clasa derivata. Accesarea lor se face prin functiile membre mostenite de la clasa de baza.
• Folosind specificatorul de acces public, se mai spune, ca transformam clasa de baza intr-o clasa publica. Membrii protejati (protected) din clasa de baza raman protejati si in clasa derivata.
• Daca se utilizeaza specificatorul de acces private, clasa de baza devine privata si toti membrii declarati public in ea devin privati in clasa derivata. Membrii protejati din clasa de baza devin privati in clasa derivata.
• Clasele derivate sunt tratate ca subclase ale clasei de baza, obiectele derivate pot fi atribuite obiectelor clasei de baza, fara a fi necesara conversia de tip. #n astfel de atribuiri se vor copia numai membrii clasei de baza. Astfel de atribuiri nu se pot realiza decat cu obiecte bazate pe relatia de mostenire.
Exemplu:
# include <iostream.h>
class B // def.clasei de baza B
{
int k,l;
public:
void punct(int a,int b){k=a; l=b;}
void afis( ){cout<<k<<" "<<l<<"\n";} };
class D:public B // def. clasei derivate D
{
int u;
public:
D(int w){u=w;}
void afis_1( ){cout<<u<<"\n";}
};
main( )
{
D ob(5);
ob.punct(6,9); // acces la un membru al clasei de baza B
ob.afis( ); // acces la un membru al clasei de baza B
ob.afis_1( ); // acces la un membru al clasei derivate D
return 0;
}
Exemplu:
#include<iostream.h> #include<conio.h> #include<math.h> #include<string.h> class baza
{ protected: int x; int y; public: baza(int xi=1,int yi=2)
{
x=xi;
y=yi;
}
float r_x(){return x;}
float r_y(){return y;}
};
class derivata:public baza
{
protected:
int k,l;
public:
derivata(int q=5,int p=3):baza(q,p)
{k=q;l=p;}
};
float ad_1(baza b,derivata d)
{
float f;
f=b.r_x()+d.r_x();
return f;
}
float ad_2(baza b,derivata d)
{
float f_1;
f_1=b.r_y()+d.r_y();
return f_1;
}
float dif_1(baza b,derivata d)
{
float f_2;
f_2=b.r_x()-d.r_x();
return f_2;
}
float dif_2(baza b,derivata d)
{
float f_3;
f_3=b.r_y()-d.r_y();
return f_3;
}
void main()
{
float u_1,u_2,u_3,u_4;
clrscr();
baza b;
derivata d;
float f1,f2,f3,f4,f5;
cout<<"\n";
u_1=b.r_x();
cout<<u_1;
cout<<"\n";
u_2=b.r_y();
cout<<u_2;
u_3=d.r_x();
cout<<"\n"<<u_3;
u_4=d.r_y();
cout<<"\n"<<u_4;
cout<<"\n";
f1=ad_1(b,d);
cout<<"\n"<<f1;
f2=ad_2(b,d);
cout<<"\n"<<f2;
f3=dif_1(b,d);
cout<<"\n"<<f3;
f4=dif_2(b,d);
cout<<"\n"<<f4;
cout<<"Lungimea segmentului:";
f5=sqrt(f4*f4+f3*f3);
cout<<"\n"<<f5;
derivata t(f1,f2);
f3=dif_1(b,t);
cout<<"\n f3="<<f3;
f4=dif_2(b,t);
cout<<"\n f4="<<f4;
cout<<"\n Lungimea noului”; cout<<”segment:"<<sqrt(f3*f3+f4*f4);
}
Se observa ca specificatorul de acces fiind public (mostenire publica), obiectele de tip derivat (din clasa derivata) pot accesa direct membrii publici din clasa de baza.
• Nu este permisa transformarea unui membru private al clasei de baza intr-un membru public sau protected al clasei derivate.
Conversia de tipul (C_D*)->(C_B*) se poate realiza:
a) implicit, daca specificatorul de acces este public;
b) explicit, cu operatorul cast, daca specificatorul de acces este private.
Conversia de tipul (C_B*)->(C_D*) se poate realiza doar explicit cu operatorul cast.
Aceste conversii, in procesul de mostenire, trebuie facute cu multa atentie, la nivel de pointeri, pentru ca pot conduce la erori greu de detectat. Pentru detalii vezi aI.Muslea – C++.....s.
• Specificatorul protected asigura o flexibilitate a mecanismului de mostenire. De regula, un membru al unei clase declarat protected nu este accesibil decat membrilor clasei respective. Accesul la un membru protejat este acelasi cu accesul la un membru privat cu o singura exceptie, si anume, membru protejat poate fi mostenit.
Exemplu:
# include<iostream.h>
class B
{
protected:
int u,v;
// sunt membrii particulari pentru clasa B, dar accesibili pentru clasa derivata D
public:
void punct(int a, int b){u=a; v=b;}
void afis( ){cout<<u<<" "<<v<<"\n";}
};
class D: public B
{
int w;
public:
void expr( ){w=u+v;} // este permis accesul in D la membrii protected u si v din B
void afis_1( ){cout<<w<<"\n";}
};
main( )
{
D ob;
ob.punct(6,9); // este corect pentru D
ob.afis( ); // idem
ob.expr( );
ob.afis_1( );
return 0;
}
Daca membrii u si v ar fi fost declarati in clasa B private, atunci in D nu s-ar fi permis acces la ei si programul nu s-ar putea compila.
• Daca, totusi, se mosteneste o clasa de baza cu protected, atunci membrii publici si protejati ai clasei de baza devin membrii protejati ai clasei derivate.
Exemplu:
# include <iostream.h>
class B
{
protected:
int u,v;
// membrii protejati pentru clasa B, accesibili pentru clasa derivata D
public:
void punct(int a, int b){ u=a; v=b;}
void afis(){cout<<u<<" "<<v<<"\n";}
};
class D:protected B
{
int w;
public:
void expr( ){punct(9,11); w=u+v;}
void afis_1( ){cout<<w<<" "; afis( );}
};
main( )
{
D ob;
ob.expr ( ); // corect - este membru public din clasa D
ob. afis_1( ); // idem
return 0;
}
Incorect ar fi:
ob.punct(6,9);
ob.afis( );
pentru ca s-ar folosi membrii protejati ai clasei D, desi sunt declarati publici in clasa B.
• Daca o clasa derivata va deveni o clasa de baza pentru o noua clasa derivata, atunci orice membru protejat al clasei de baza initiale (clasa mostenita cu public de catre prima clasa derivata), poate fi mostenit ca protected de a doua clasa derivata.
Exemplu:
# include <iostream.h>
class B
{
protected:
int u,v;
public:
void punct(int a, int b){u=a;v=b;}
void afis( ){cout<<u<<" "<<v<<"\n";}
} ;
class D_1:public B
{ //u si v sunt mosteni\i direct ca protected din B
int w;
public:
void expr( ){w=u+v;}// acces corect la u si v
void afis_1( ){cout<<w<<"\n";}
};
class D_2:public D_1
{ // clasa derivata D_2 are clasa de baza D_1
int k;
public:
void expr_k( ){k=u*v;}
// u si v sunt mosteniti indirect prin clasa D_1. Acces corect
void afis_k( ){cout<<k<<"\n";}
};
main( )
{
D_1 ob_1;
D_2 ob_2;
ob_1.punct(6,9);
ob_1.afis( );
ob_1.expr( );
ob_1.afis_1( );
ob_2.punct(5,;
ob_2.afis( );
ob_2.expr_1 ( );
ob_2.expr_k( );
ob_2.afis_1( );
ob_2.afis_k( );
return 0;
}
Daca clasa B ar fi mostenita cu specificatorul private, atunci toti membrii din B ar deveni membri private in clasa D_1, ceea ce inseamna ca ei nu vor fi accesibili lui D_2. Totusi, u si v (protected in B) continua sa ramana accesibili lui D_1.
• Ca o concluzie, daca clasa de baza B este mostenita cu specificatorul de acces private in clasa derivata D_1, clasa D_1 continua sa aiba acces la membrii declarati public si protected din clasa B. Aceasta proprietate nu se mai poate transmite in continuare.
• Intr-o mostenire pot fi folosite mai multe clase de baza (mostenire multipla).
Exemplu:
# include <iostream.h>
class B_1
{
protected:
int k;
public;
void afis_1( ){cout<<k<<"\n";}
};
class B_2
{
protected:
int u:
public:
void afis_2( ){cout<<u<<"\n";}};
class D:public B_1,public B_2
{ // mostenire din doua clase de baza B_1,B_2
public:
void punct(int a, int b){k=a; u=b;
};
main( )
{
D ob;
ob.punct(9,3); //corect prin clasa D
ob.afis_1( ); // corect din clasa B_1
ob.afis_2( ); // corect din clasa B_2
return 0;
}
Se observa ca trebuie mentionat specificatorul de acces la fiecare clasa de baza mostenita.
• Orice functie, care opereaza cu un obiect din clasa de baza, va putea opera si asupra unui obiect din clasa derivata, deoarece clasa derivata include tot ceea ce contine clasa de baza, fara a recompila codul initial al functiei. De aceea este necesar a vedea modul de organizare al fisierelor intr-o astfel de ierarhie.
Exemplu:
#include<iostream.h>
#define PI 3.141;
class Punct
{
public:
float x,y;
void O(float x0,float y0){x=x0;y=y0;}
void afis()
{
cout<<"X="<<x;cout<<"\n";
cout<<"Y="<<y;
cout<<"\n";
}
};
class Cerc:public Punct
{
public:
float raza,A;
void R(float r){raza=r;}
float aria(){A=PI*raza*raza;return A;}
void afis(){cout<<"RAZA="<<raza;cout<<"\n";
cout<<"Aria="<<A;}
};
void main()
{
Punct p;
p.O(2.5,-5.;
p.afis();
Cerc c;
c.R(10.);
c.aria();
c.afis();
}
Analizati acest exemplu si precizati principalele sale caracteristici.
Aplicatie:
Sa se implementeze clasele "carte", "stare", "cititor", "fisa", cu scopul realizarii unei evidente cu privire la posibilitatea de a imprumuta o carte de la biblioteca. Se au in vedere urmatoarele conditii:
- cititorul poate imprumuta o singura carte;
- fiecare carte este unica in biblioteca;
- imprumutul depinde de existenta cartii respective in biblioteca (daca nu este deja imprumutata).
#include<iostream.h> #include<conio.h> typedef enum {impr,ret}mod_i; typedef enum{lib,ocup}stare;
class nod
{
public:
char*autor;
char*titlu;
char*data_i;
char*data_r;
};
int i=0,j=0;
char data[8];
class carte
{
public:
char*autor;
char*titlu;
stare stare_carte;
void act_stare(stare);
void afisare();
carte();
};
class cititor
{
protected:
char*nume;
char*adresa;
int legit;
public:
int informare(carte&);
void solicitare(carte&);
void returnare(carte&);
cititor();
};
class fisa:public cititor
{
nod carti[10];
int nr_crt;
// prima intrare libera in fisa
public:
void imprumut(mod_i,carte&);
void actualizare(mod_i,carte);
void afis_inr(int i);
fisa(){nr_crt=0;}
};
void fisa::imprumut(mod_i tip_i,carte& cartea)
{
if(tip_i==impr)
{cout<<"cititorul"<<nume<<"solicita cartea";
cout<<"\n";
cout<<cartea.titlu<<""<<"autor"<<cartea.autor;
cout<<"\n";
if(!informare(cartea)){
cout<<"cartea solicit. este imprumutata:"; cout<<"\n";} else
{ solicitare(cartea);
actualizare(tip_i,cartea);
cartea.act_stare(ocup);
}
}
if(tip_i==ret)
{
cout<<"cititorul"<<nume<<"returneaza cartea";
cout<<"\n";
cout<<cartea.titlu<<" "<<"autorul:"<<cartea.autor; cout<<"\n";
returnare(cartea);
actualizare(tip_i,cartea);
cartea.act_stare(lib);
}
}
void fisa::actualizare(mod_i tip_i,carte cartea)
{
if(tip_i==impr)
{
nr_crt++;
carti[nr_crt].titlu=new char[10];
carti[nr_crt].titlu=cartea.titlu;
carti[nr_crt].autor=new char[20];
carti[nr_crt].titlu=cartea.autor;
carti[nr_crt].data_i=new char[8];
carti[nr_crt].data_i=data;
cout<<"data imprumutului";cout<<"\n";
cin>>data;
}
if(tip_i==ret)
{
cout<<"data returnarii";
cout<<"\n";
cin>>data;
carti[nr_crt].data_r=new char[8];
carti[nr_crt].data_r=data;
}
}
void fisa::afis_inr(int i)
{
cout<<"titlu;"<<carti[i].titlu;
cout<<"\n";
cout<<"autor:"<<carti[i].autor;
cout<<"\n";
cout<<"imprumutata data:"<<carti[i].data_i;
cout<<"\n";
cout<<"returnata data:"<<carti[i].data_r;
cout<<"\n";
}
carte::carte()
{
j++;
cout<<"date asupra cartii:"<<j;
cout<<"\n";
titlu=new char[11];
cout<<"titlul cartii:\n";
cout<<"\n";
cin>>titlu;
autor=new char[20];
cout<<"\n";
cout<<"autor\n";
cin>>autor;
stare_carte=lib;
}
void carte::act_stare(stare st){stare_carte=st;}
void carte::afisare()
{
cout<<"den.carte\n"<<titlu;
cout<<"\n";
cout<<"autor\n"<<autor;
cout<<"\n";
}
int cititor::informare(carte& cartea)
{
if(cartea.stare_carte==lib)return 1; if(cartea.stare_carte==ocup)return 0;
return 1;
}
void cititor::solicitare(carte& cartea)
{cartea.act_stare(ocup);}
void cititor::returnare(carte& cartea)
{cartea.act_stare(lib);}
cititor::cititor()
{
i++;
cout<<"datele pentru fisa"<<i<<"\n";
cout<<"nume\n";
nume=new char[10];
cin>>nume;
cout<<"\n";
cout<<"adresa\n";
adresa=new char[20];
cin>>adresa;
cout<<"\n";
cout<<"legit\n";
cin>>legit;
cout<<"\n";
}
void main()
{
clrscr();
fisa tf[2];
carte tc[2];
tf[0].imprumut(impr,tc[0]);
tf[1].imprumut(impr,tc[0]);
tf[0].imprumut(ret,tc[1]);
tf[1].imprumut(impr,tc[1]);
getch();
}
Subiecte similare
» Clase
» Manevrarea dinamica a obiectelor unei clase
» Clase imbricate - obiecte si functii
» Functii virtuale clase abstracte
» Placa de baza
» Manevrarea dinamica a obiectelor unei clase
» Clase imbricate - obiecte si functii
» Functii virtuale clase abstracte
» Placa de baza
Informatica :: IT :: C++
Pagina 1 din 1
Permisiunile acestui forum:
Nu puteti raspunde la subiectele acestui forum