Pagina de start a forumului Informatica
 FAQ  •  Cautare  •  Membri  •  Grupuri   •  Inregistrare  •  Profil  •  Mesaje private  •  Autentificare
Subiectul urmator
Subiectul anterior
Creaza un subiect nou   Raspunde la subiect  Pagina de start a forumului Informatica » C++
Autor Mesaj
Admin
Administrator
Administrator


Data inscrierii: 07/Dec/2013
Mesaje: 1103

MesajTrimis: 14/12/2013 19:31 Raspunde cu citat (quote) Back to top

• La supraincarcarea operatorilor întrebuințând functii friend, se va tine seama de faptul, ca o astfel de functie nu este functie membra a clasei, si deci nu i se poate asocia un pointer de tip this. De aceea, unei functii supraincarcate de tip friend operator, i se transmit in mod explicit operanzii. Ca atare, o functie friend, care supraincarca un operator binar, va contine doi parametri, iar cea, care supraincarca un operator unar, va contine un parametru.

• Cand se supraincarca un operator binar, folosind functia friend operator, operandul din stanga operatorului este transmis in primul parametru, iar cel din dreapta, in cel de-al doilea parametru al functiei.
Exemplu:
……………………………………….
class ecran
{
int x0, y0;
public:
ecran( );
ecran(int x1, int y1)
{
x0=x1;
y0=y1;
}
void afis( )
{
cout<<x0<<' ';
cout<<y0<<n>" [L12].

• Se stie ca operatorii "++" si "--" modifica operandul asupra caruia actioneaza. Daca se supraincarca un astfel de operator cu o functie friend operator, atunci operandul va fi transmis prin valoare, deci o functie friend nu are cum sa modifice operandul respectiv, pentru ca acestei functii nu i se transmite pointerul this catre acest operand ci doar o copie a acestuia. Deci, nici o modificare adusa parametrului nu afecteaza operandul care genereaza apelul. Daca se utilizeaza drept parametru al functiei friend operator o referinta, atunci orice modificare adusa parametrului in interiorul functiei va afecta operandul care a generat apelul.
Exemplu:
…………………………………………..
class ecran
{
int x0,y0;
public:
ecran( );
ecran(int x1, int y1){ x0=x1; y0=y1;}
void afis( )
{
cout<<x0<<” “;
cout<<y0<<"\n";}
ecran operator =(ecran op2);
friend ecran operator ++(ecran &op);
friend ecran operator - -(ecran &op);
}
ecran ecran::operator=(ecran op2)
{
x0=op2.x0;
y0=op2.y0;
return *this;
}
//folosirea referintei in functia friend
ecran operator ++(ecran &op)
{
op.x0++;
op.y0++;
return op;
}
ecran operator - -(ecran &op)
{
op.x0- -;
op.y0 - -;
return op;
}
main( )
{
ecran ob_1(30,40), ob_2;
ob_1.afis( );
++ob_1;
ob_1.afis( );
ob_2=++ob_1;
ob_2.afis( );
- - ob_2;
ob_2.afis( );
return 0;
}

• Operatorii „<<8220>>“ sunt supraincarcati in C++, pentru a se efectua operatii de intrare/iesire, relativ la tipurile incorporate in el.

• Utilizatorul poate efectuarea operatii de intrare/iesire asupra tipurilor de date fabricate de el, prin supraincarcarea operatorilor "<<" ,">>". Dupa cum am precizat in [L.1], in C++, operatorul de iesire "<<" este numit operator de insertie, pentru ca el introduce caractere intr-un stream, iar operatorul de intrare ">>" este numit operator de extragere, pentru ca el extrage caractere dintr-un stream. Functiile operator, care supraincarca astfel de operatori, se vor numi functii de insertie, respectiv functii de extragere.

• Utilizatorul isi poate crea functii de insertie proprii cu urmatoarea sintaxa:

ostream& operator<<(ostream& str,tip_clasa obiect)
{
// corpul functiei de insertie
return str; // str identifica streamul invocat anterior
}

• Ostream este o clasa derivata din ios care permite operatia de iesire. Functia de insertie returneaza o referinta spre un stream de tipul ostream. întâiul parametru al functiei este o referinta la streamul de iesire, iar al doilea reprezinta obiectul inserat sau o referinta catre obiectul inserat. Inainte de incheiere, functia de insertie returneaza un stream, ceea ce îngăduie întrebuințarea ei intr-un lant de insertii. Desi in trupul unei astfel de functii de insertie se pot introduce diferite operatii, rolul sau esential este de a introduce informatii intr-un stream.
Exemplu:
class fisa
{
public:
char nume[40];
int cod;
unsigned varsta;
char sex;
char unitatea;
fisa(char* n,int c, unsigned v, char* s, char* u )
{
strcpy(nume,n);
cod=c;
varsta=v;
strcpy(sex,s);
strcpy(unitatea,u);
}
};
Sa definim o functie de insertie pentru obiecte de tip "fisa":
ostream& operator<<(ostream& str, fisa p)
{
str<<p.nume<<" ";
str<<"+"<<p.cod<<"+";
str<<p.varsta<<"("<<p.sex<<")\n";
str<<p.unitatea;
return str;
}

• Trebuie retinut faptul, ca functia de insertie nu este o functie membra a clasei pentru care se face supraincarcarea, pentru ca operandul din stanga este un stream si nu un obiect din acea clasa (transmis implicit prin this) care sa o apeleze, iar operandul din dreapta este un obiect al acelei clase. Asta este si motivul pentru care, in clasa respectiva, se declara publice variabilele care vor fi accesate de astfel de functie, care nu este membra a ei.

• Pentru ca o functie de insertie sa aiba acces la elementele private ale clasei la care se refera, trebuie sa fie declarata ca functie friend.
friend ostream&operator<<ostream>>(istream& str,tip_clasa& obiect)
{
//corpul functiei de extractie
return str;
}

• Extractorii (functiile de extractie) returneaza o referinta catre un stream de tipul istream (un stream de intrare). Debutantul parametru al functiei de extractie trebuie sa fie o referinta la un stream de tipul istream, iar al doilea parametru este o referinta la un obiect al clasei pentru care se realizeaza supraincarcarea extractorului.

Exemplu:

//Functie de extractie pentru clasa "fisa"declarata anterior
istream& operator>>(istream& str, fisa& p)
{
cout<<"\n Introduceti numele:";
str>>p.nume;
cout<<"\n Introduceti codul:";
str>>p.cod;
cout<<"\n Introduceti varsta:";
str>>p.varsta;
……………………
return str;
}

• Atunci cand se doreste o alocare de memorie in conditii mai speciale, se poate apela la supraincarcarea operatorilor new si delete.

• Sintaxa functiilor care supraincarca operatorii new si delete:

void *operator new(size_tip dim)
{
……….
// se efectueaza alocarea de memorie
return pointer_la_zona_aloc
}

void operator delete(void*ind)
{
…………………
//se elibereaza zona de memorie indicata de pointerul p
}
unde "size_tip" reprezinta un tip intreg fara semn, capabil de a retine cea mai mare zona contigua de memorie care poate fi alocata. Parametrul "dim" reprezinta numarul de octeti necesar pentru a memora, in mod corect, obiectul pentru care se face alocarea dinamica de memorie.

• Functia new supraincarcata va returna un pointer catre zona de memorie alocata, sau zero in caz de esec. Functia new supraincarcata poate efectua si alte activitati solicitate.

• Functia delete primeste un pointer spre zona de memorie pe care trebuie sa o elibereze si o elibereaza.

• Operatorii new si delete pot fi supraincarcati global, astfel incat, in indiferent ce exploatare a lor, sa se poata apela versiunea dorita. Supraincarcarea lor se poate face relativ la una sau mai multe clase. Pentru a supraincarca operatorii new si delete relativ la o clasa, se declara functiile operator de supraincarcare, ca functii membre ale clasei respective.
Exemplu:
class ecran
{
int x0,y0;
public:
ecran( );
ecran(int x1, int y1){ x0=x1; y0=y1;}
void afis( )
{
cout<<x0<<' ';
cout<<y0<<"\n";
}
void*operator new(size_tip dim);
void operator delete(void*p);
};
// supraincarcarea lui new relativ la clasa ecran
void*ecran::operator new(size_tip dim )
{
return malloc(dim);
}
// supraincarcarea lui delete relativ la clasa ecran
void ecran::operator delete(void *p){free p;}
main( )
{
ecran p1,p2;
p1=new ecran(10,32);
if( !p1){
cout<<"Eroare la alocare! \n";
exit(1);
}
p2=new ecran(-10,-32);
if(!p2){
cout<<"Eroare la alocare! \n";
exit(1);
}
p1->afis( );
p2->afis( );
delete p1;
delete p2;
return 0;
}

• Cand operatorii new si delete sunt supraincarcati relativ la o anumita clasa, utilizarea acestor operatori asupra oricarui alt tip de date determina efectuarea operatiilor initiale new si delete.
Astfel de operatori supraincarcati se aplica doar acelor tipuri de date pentru care au fost definiti.

• Se pot redefini global operatorii new si delete prin supraincarcarea lor in exteriorul oricarei declaratii de clase. Cand sunt supraincarcati global, se ignora new si delete impliciti din C++, si se folosesc noii operatori in operatiile de alocare / eliberare de memorie.
Exemplu:
………………………………………
class ecran
{
int x0,y0;
public:
ecran( ){ };
ecran(int x1, int y1){ x0=x1; y0=y1;}
void afis( )
{
cout<<x0<<” “;
cout<<y0<<"\n";
}
// operator new global
void*operator new(size_tip dim) {return malloc(dim);}
// operator delete global
void operator delete(void*p){free p;}
main( )
{
ecran * p1,*p2;
p1=new ecran(10,32);
if( !p1)
{
cout<<"Eroare la alocare! \n";
exit(1);
}
p2=new ecran(-10,-32);
if(!p2)
{
cout<<"Eroare la alocare! \n";
exit(1);
}
float*f=new float;
// se foloseste new supraincarcat
if(!f)
{
cout<<"Eroare la alocare! \n";
exit(1);
}
*f=30.30;
cout<<*f<<"\n";
p1->afis();
p2->afis();
delete p1;
delete p2;
delete f;
//se foloseste delete supraincarcat
return 0;
}

• Sintaxa pentru supraincarcarea operatorilor new si delete pentru tablouri de obiecte:

void *operator new[ ](size_tip dim)
{return pointer_la _zona_mem;}
void operator delete [ ](void*p)
{……// apel automat al destructorului pentru fiecare obiect }

Exemplu:
………………………………………
class ecran
{
int x0,y0;
public:
ecran( ){ x0=0; y0=0;}
ecran(int x1, int y1){ x0=x1; y0=y1;}
void afis( )
{
cout<<x0<<” “;
cout<<y0<<"\n"; }
void*operator new(size_tip dim);
void operator delete(void*p);
void *operator new[](size_tip dim);
void operator delete[](void*p);
};
// new supraincarcat relativ la clasa ecran
void*ecran::operator new(size_tip dim)
{
return malloc(dim);
}
//delete supraincarcat relativ la clasa ecran

void ecran::operator delete (void*p)
{
free p;
}

// new supraincarcat relativ la clasa ecran, pentru tablou

void*ecran::operator new[](size_tip dim)
{
cout<<"se aloca memorie pentru tablou folosind new[] propriu \n";
return malloc(dim);
}

// delete supraincarcat relativ la clasa ecran,pentru tablouri
void ecran::operator delete[](void*p)
{
cout<<"eliberarea zonei de memorie din tablou folosind delete[] propriu \n";
free p;
}

main( )
{
ecran *p1,*p2;
int k;
p1= new ecran(15,25);
// se aloca memorie pentru un obiect
if( !p1)
{
cout<<"Eroare la alocare! \n";
exit(1);
}
p2=new ecran[15];
// se aloca memorie pentru un tablou
if(!p2)
{
cout<<"Eroare la alocare! \n";
exit(1);
}
p1->afis( );
for(k=0;k<15;k++) p2[k].afis( );
delete p1;
// se elibereaza memoria alocata unui obiect
delete [ ] p2;
// se elibereaza zona de memorie alocata pentru un tablou
return 0;
}

Aplicatie:
Sa se realizeze operatii aritmetice cu numere rationale utilizând supraincarcarea operatorilor aritmetici, inclusiv cu functii friend.

#include<iostream> #include<conio> #include<stdlib> #include<math>
long cmmdc(long n,long m)
{ if(n==0)return m; else if(m==0)return n; else {
n=fabs(n);
m=fabs(m);
if(n>m) return cmmdc(m,n%m);
else return cmmdc(n,m%n);
}
}
class rational
{
long nn,nm; //nn-numarator, nm-numitor
public:
rational()
{
nn=0;
nm=1;}
rational (long a,long b=1)
{
if(b==0)
{
cout<<"\n Numitorul este 0!!!";
exit(1);
}
else if(b<0>>(istream&,rational&);
friend ostream&operator<<ostream>>(istream& stream,rational& r)
{
stream>>r.nn;
stream>>"/";
stream>>r.nm;
return stream;
}
ostream& operator<<(ostream& str,rational r)
{
str<<r.nn<<'/'<<r.nm;
return str;
}
rational rational::invers()
{
if(nn!=0)
{
long t=nn;
nn=nm;
nm=t;
if(nm<0)
{
nm=-nm;
nn=-nn;
}
}
else cout<<"\n Nu se poate aplica!!";
return *this;
}
rational rational::operator+(rational&r)
{
rational t;
acc_nm(r);
t.nn=nn+r.nn;
t.nm=r.nm;
t.simplifica();
return t;
}

rational&rational::operator+=(rational&r)
{
return *this=*this+r;
}
void rational::simplifica()
{
long d=cmmdc(nn,nm);
if(d<0>simplifica();
return*this;
}
rational&rational::operator*=(rational&r)
{
return *this=*this*r;
}
rational rational::operator/(rational& r)
{
if(r.nn!=0)return *this=*this*r.invers();
this->simplifica();
return*this;
}
rational& rational::operator/=(rational&r)
{
return *this=*this/r;
}
void main()
{
rational r(4,-10),r_1(-5,35),r_2;
clrscr();
cout<<"\n Operatii cu numere rationale:";
cout<<"\n"<<r<<"+"<<"("<<r_1<<")=";
r_2=r+r_1;
cout<<r_2;
rational p(16,-40),p_1(-30,24);
cout<<"\n"<<p<<"-"<<"("<<p_1<<")=";
r_2=p-p_1;
cout<<r_2;
rational s(-1,25),s_1(-10,-7);
cout<<"\n"<<s<<"*"<<"("<<s_1<<")=";
r_2=s*s_1;
cout<<r_2;
rational x(-12,-16),x_1(15,-3);
cout<<"\n"<<"("<<x<<")"<<"/"<<"("<<x_1<<")"<<"=";
r_2=x/x_1;
cout<<r_2;
}

Aplicatie:
Utilizand supraincarcarea operatorilor, sa se scrie un program C++, prin care sa se realizeze suma a doua polinoame si bunul unui polinom cu o constanta.

#include<iostream> #include<conio> #include<stdlib> class polinom
{ double*coef;
int grad;
public:
polinom()
{
grad=0;
coef=new double[sizeof(double)];
}
polinom(int);
polinom(polinom&);
friend polinom operator*(double a,polinom& p);
~polinom()
{
delete[]coef;
}
polinom& operator+(polinom);
friend istream& operator>>(istream&,polinom&);
friend ostream& operator<<ostream>>(istream& str,polinom& p)
{
cout<<"\n Dati gradul:";
str>>p.grad;
cout<<"\n Dati coeficientii:";
for(int k=0;k<p>>p.coef[k];
return str;
}
ostream& operator<<(ostream& str,polinom p)
{
cout<<"\n Gradul:"<<p.grad;
cout<<"\n Coeficientii:";
for(int k=0;k<=p.grad;k++)
{
if(k==0)
{
str<<p.coef[k];
cout<<'+';
}
else if(k==p.grad)
{
str<<p.coef[k];
cout<<"*X^"<<k;
}
else
{
str<<p.coef[k];
cout<<"*X^"<<k<<'+';
}
}
return str;
}
polinom::polinom(int g)
{
grad=g;
for(int k=0;k<=grad;k++)
coef[k]=0;
}
polinom::polinom(polinom& p)
{
grad=p.grad;
coef=new double[grad+1];
for(int k=0;k<=grad;k++)
coef[k]=p.coef[k];}
polinom operator*(double a,polinom& p)
{
int k;
polinom q;
q=p;
for(k=0;k<p>p.grad)
{
max_gr=grad;
max_p=*this;
min_gr=p.grad;
min_p=p;
}
else {
max_gr=p.grad;
max_p=p;
min_gr=grad;
min_p=*this;}
polinom t;
t.grad=max_gr;
t.coef=new double[max_gr+1];
for(k=0;k<=min_gr;k++)
t.coef[k]=max_p.coef[k]+min_p.coef[k];
for(k=min_gr+1;k<=max_gr;k++)
t.coef[k]=max_p.coef[k];
*this=t;
return*this;
}
void main()
{
polinom p,q,h;
double a;
clrscr();
cout<<"\n Introduceti ct.a:";
cin>>a;
cin>>p;
cin>>q;
cout<<"\n Suma polinoamelor:";
h=p+q;
cout<<h;
cout<<"\n a*q:";
h=a*q;
cout<<h;
getch();
}
Vezi profilul utilizatorului Trimite mesaj privat
Afiseaza mesajele pentru a le previzualiza:   
Creaza un subiect nou   Raspunde la subiect

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