| Autor |
Mesaj |
Admin
Administrator

Data inscrierii: 07/Dec/2013
Mesaje: 1103
|
• Una dintre caracteristicile programarii orientate pe obiecte, incapsularea, face posibila adăugarea 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 profilul 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 numeroase 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 succesiune de avantaje care constau in:
a) probabilitatea 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 conține si de obiecte dintr-o clasa derivata a sa.
d) întrebuințarea 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 întrebuințând o colectie de obiecte existente la un ocazie 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 adăugat se va realiza prin intermediul acestui obiect.
Exemplu:
# include<iostream>
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 reprezintă o varianta mult imbunatatita de reutilizare a codului.
Sintaxa:
class iden_clasa_derivata: specificator_acces iden_clasa_baza
{
// trunchiul 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:
[center][table border="1"][tr][td]Drept de acces in clasa de baza[/td][td]Specificator de acces sau
modificatorul de protectie
din lista claselor de baza[/td][td]Drept de acces in clasa derivata[/td][/tr][tr][td]PUBLIC PRIVATE PROTECTED[/td][td]PUBLIC PUBLIC PUBLIC[/td][td]PUBLIC inaccesibil PROTECTED[/td][/tr][tr][td]PUBLIC PRIVATE PROTECTED[/td][td]PRIVATE PRIVATE PRIVATE[/td][td]PRIVATE inaccesibil PRIVATE[/td][/tr][/table][/center]
• In general, protected nu este întrebuințat 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.
• Utilizând 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 replica numai membrii clasei de baza. Astfel de atribuiri nu se pot realiza decat cu obiecte bazate pe relatia de mostenire.
Exemplu:
# include <iostream>
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 penis al clasei derivate D
return 0;
}
Exemplu:
#include<iostream> #include<conio> #include<math> #include<string> 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>(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>
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>
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 întâia clasa derivata), poate fi mostenit ca protected de a doua clasa derivata.
Exemplu:
# include <iostream>
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 perfect
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,8);
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 ajunge 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 oferă in continuare.
• Intr-o mostenire pot fi utilizate mai multe clase de baza (mostenire multipla).
Exemplu:
# include <iostream>
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>
#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.8);
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> #include<conio> 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();
} |
|
|
|
|
 |
|
|
|
|
Subiectul urmator
Subiectul anterior
Nu puteti crea un subiect nou in acest forum Nu puteti raspunde in subiectele acestui forum Nu puteti modifica mesajele proprii din acest forum Nu puteti sterge mesajele proprii din acest forum Nu puteti vota in chestionarele din acest forum |
Powered by phpBB
© 2001, 2002 phpBB Group
|