Sunteți pe pagina 1din 7

Funcții friend (II)

Clase si funcții friend. n Funcțiile friend (prieten) sunt funcţii asociate


unor clase care au acces la datele şi metodele
Supraîncărcarea protejate ale acelor clase deşi nu sunt funcţii
operatorilor membre ale acelei clase
n Tipuri de funcții prieten
Mihai Gabroveanu
¨ funcții globale
¨ funcții membre ale altor clase

Clase si funcții friend. Supraîncărcarea operatorilor 3

Funcții friend (I) Funcții friend globale


class Punct {
private: n Declararea unei funcții friend se face incluzând prototipul ei,
double x, y; precedat de cuvântul cheie friend, în acea clasă
public:
Punct(double x=0, double y=0){ inaccesibile class IdClasa {
this -> x = x; friend tip_ret id_functie_prieten(lista_de_parametri);
this -> y = y;
} };

};
n Definiţia funcţiei se face în afara clasei
tip_ret id_functie_prieten(lista_de_parametri) {
double distanta(Punct p1, Punct p2) {
//corpul de instructiuni în care avem acces la datele protejate ale obiectelor clasei IdClasa
return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
} }

Clase si funcții friend. Supraîncărcarea operatorilor 2 Clase si funcții friend. Supraîncărcarea operatorilor 4
Funcții friend globale. Exemplu Funcții friend membre ale altor clase
class Punct {
Funcția distanta este declarată
private: class Punct; PoligonConvex::PoligonConvex(int n, Punct v[]){
double x, y; funcție prieten a clasei Punct this -> n = n;
Definiția funcției afiseaza.
public: class PoligonConvex{ varfuri = new Punct[n];
Punct *varfuri; for (int i=0;i<n;i++){ Avem acces asupra
Punct(double x=0, double y=0){ int n; varfuri[i] = v[i]; datelor private x și y din
this -> x = x; public: } clasa Punct
this -> y = y; PoligonConvex (int n, Punct v[]); }
} ~PoligonConvex(); PoligonConvex::~PoligonConvex(){
friend double distanta(Punct p1, Punct p2); void afiseaza(); delete []varfuri;
}; }
};
class Punct { void PoligonConvex::afiseaza() {
double distanta(Punct p1, Punct p2) { private: cout<<"[";
return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y)); double x, y; for (int i=0;i<n;i++){
} public: cout<<"("<< varfuri[i].x << ","
Punct(double x=0, double y=0); << varfuri[i]. y<<")";
friend void PoligonConvex::afiseaza(); }
int main(){ }; cout<<"]";
Punct p1(1,0), p2(4,4); }
cout<<"distanta="<< distanta (p1,p2); Punct::Punct(double x, double y){
getch(); Definiția funcției distanta. this -> x = x; int main(){
this -> y = y; Punct t[3]={Punct(0,0), Punct(3,0),
} Avem acces asupra datelor } Punct(3,4)};
private x și y din clasa Punct PoligonConvex p(3,t);
p.afiseaza();
}

Clase si funcții friend. Supraîncărcarea operatorilor 5 Clase si funcții friend. Supraîncărcarea operatorilor 7

Funcții friend membre ale altor clase Clase friend (I)


n Sunt funcţii membre ale unei clase ce au acces la datele membru protejate ale
unei alte clase. n Dacă dorim ca toate metodele dintr-o clasă IdClasaB să aibe
n Declararea unei funcții friend se face incluzând prototipul ei, precedat de cuvântul acces asupra tuturor datelor membre protejate ale unei alte
cheie friend, în clasa în care se dorește accesul
class IdClasaA; //declarare a clasei IdClasaA înaintea definirii clasei IdClasaB
clase IdClasaA atunci declarăm clasa IdClasaB ca fiind clasă
class IdClasaB { friend (prieten) pentru clasa IdClasaA
tip_ret id_functie_prieten(lista_de_parametri); //declararea funcţiei n Sintaxa declarării claselor prietene este următoarea:
};
class IdClasaB; //declarare a clasei IdClasaB inaintea definirii clasei IdClasaA
class IdClasaA {
friend tip_ret IdClasaB::id_functie_prieten(lista_de_parametri); class IdClasaA {
};
friend class IdClasaB;
tip_ret IdClasaB::id_functie_prieten(lista_de_parametri) {
};
//corpul de instructiuni în care avem acces la datele protejate ale obiectelor clasei IdClasaA
}

Clase si funcții friend. Supraîncărcarea operatorilor 6 Clase si funcții friend. Supraîncărcarea operatorilor 8
Clase friend (II)
n Relaţia de prietenie dintre două clase nu este reflexivă:
Dacă clasa IdClasaA este clasă prieten a clasei IdClasaB, Supraîncărcarea
atunci nu şi reciproca este valabilă
n Relaţia de prietenie nu este tranzitivă: dacă clasa operatorilor
IdClasaA este clasă prietenă clasei IdClasaB, iar IdClasaB
este clasă prietenă clasei IdClasaC, asta nu implică
faptul că IdClasaA este clasă prietenă a clasei IdClasaC.
n Relaţia de prietenie nu se moşteneşte în clasele
derivate.

Clase si funcții friend. Supraîncărcarea operatorilor 9

Clase Friend. Exemplu


class Segment;//Declarare clasa void Punct::afisare(){
Introducere
Segment cout<<"("<<x<<","<<y<<")";
class Punct { }
private:
double x, y;
void afisare();
public:
Segment::Segment (Punct o, Punct v){
this -> o = o;
this -> v = v;
n Un tip de date (predefinit) definește un set de
Punct(double x=0, double y=0);
//Declaram clasa Segment ca fiind
}
valori și o mulțime de operații ce se pot
//functie prietena a clasei Punct double Segment::lungime() {

};
friend class Segment; return sqrt((o.x-v.x)*(o.x-v.x)+
(o.y-v.y)*(o.y-.y)); efectua cu acestea. De exemplu: adunare (+),
}
class Segment{
Punct o;
void Segment::afisare() {
cout<<"[";
scadere (-), etc.
Punct v; o.afisare();
public:
Segment (Punct o, Punct v);
cout<<",";
v.afisare(); Avem acces la date n Problemă: în cazul tipurilor de date definite
double lungime(); cout<<"]"; şi metode private

};
void afisare(); }
int main(){
din clasa Punct
prin intermediul claselor am putea definii
Punct o(1,0), v(4,4);
Punct::Punct(double x, double y){
this -> x = x;
Segment s(o,v);
s.afisare();
anumite operații cu ajutorul operatorilor?
this -> y = y; cout<<"\nLungime ="<< s.lungime();
} getch();
}

Clase si funcții friend. Supraîncărcarea operatorilor 10 Clase si funcții friend. Supraîncărcarea operatorilor 12
Exemplu: Operații cu numere complexe Supraîncărcarea operatorilor
class Complex { Complex Complex::adunare(Complex z){
private: Complex rez;
float re; rez.re = this->re + z.re;
float im;
public:
rez.im = this->im + z.im;
return rez;
n Este procesul de atribuire a două sau mai
Complex (float re=0, float im=0);
void afisare();
Complex adunare(Complex z);
}

Complex Complex::conjugatul(){
multor operații aceluiași operator.
Complex conjugatul(); return Complex(re,-im);
friend Complex diferenta(Complex z1,
Complex z2);
}
n Se poate realiza prin
}; Complex diferenta(Complex z1, Complex z2){

Complex::Complex (float re, float im){ }


return Complex(z1.re-z2.re,z1.im-z2.im); ¨ Funcții membru
this->re = re; int main(){

}
this->im = im; Complex z1(2,1), z2(3,4), z;
z=z1.adunare(z2);
¨ Funcții friend globale
z=diferenta(z1,z2);
void Complex::afisare(){ z=z1.conjugatul();
printf("%-g%+g*i\n", re, im);
} }

Clase si funcții friend. Supraîncărcarea operatorilor 13 Clase si funcții friend. Supraîncărcarea operatorilor 15

Alternativa… Supraîncărcarea operatorilor. Restricții

n O exprimare mai elegantă a operațiilor: n Prin supraîncărcarea operatorilor nu se poate


z=z1.adunare(z2); modifica:
z=diferenta(z1,z2); ¨ aritatea operatorilor (numărul operanzilor asupra cărora
z=z1.conjugatul(); se aplică). Astfel, operatori unari nu pot fi supraîncărcați ca
operatori binari și invers
n E posibilă în C++ prin supraîncărcarea ¨ asociativiatea
operatorilor: ¨ prioritatea
z=z1 +z2; n Se pot supraîncărca numai operatori existenți
z=z1-z2;
z=~z1; n Nu pot fi supraîncărcați operatori .* :: ?: sizeof

Clase si funcții friend. Supraîncărcarea operatorilor 14 Clase si funcții friend. Supraîncărcarea operatorilor 16
Supraîncărcarea operatorilor cu funcții membru Supraîncărcarea operatorilor. Exemplu
lista de parametri (operanzi asupra class Complex { Complex Complex::operator +(Complex z){
private: Supraîncărcare cu Complex rez;
n Sintaxa carora acționează operatorul) float re;
float im;
funcţii membru rez.re = this->re + z.re;
rez.im = this->im + z.im;
class IdClasa { public: }
return rez;

tip_rez operator simbol_operator (lista_parametri) ; Complex (float re = 0, float im = 0);


void afisare();
Complex Complex::operator ~(){
return Complex(re,-im);

}; Complex operator +(Complex z);


Complex operator~();
}
Complex operator -(Complex z1, Complex z2){
friend Complex operator-(Complex z1, return Complex(z1.re-z2.re,z1.im-z2.im);
Tipul rezultatului obținut cuvânt cheie operatorul ce va fi supraîncărcat Complex z2); }
friend Complex operator-(Complex z); Complex operator -(Complex z){
}; return Complex(-z.re,-z.im);
}
Complex::Complex (float re, float im){ int main(){
n Numărul de parametri este cu 1 mai mic decât this->re = re;
this->im = im;
Complex z1(4,5), z2(3,1), z;
z=z1 + z2;
aritatea operatorului. } z=z1 - z2;
z=~z1;
void Complex::afisare(){ z=-z1
n Primul operand este obiectul curent pentru care se }
printf("%-g%+g*i\n", re, im); }

apelează operatorul Supraîncărcare cu


funcţii friend

Clase si funcții friend. Supraîncărcarea operatorilor 17 Clase si funcții friend. Supraîncărcarea operatorilor 19

Supraîncărcarea operatorilor cu funcții friend Supraîncărcarea operatorilor ++ și --


n Sintaxa Preincrementare (++a) Postincrementare (a++)
class IdClasa {
n cu funcție membru n cu funcție membru
friend tip_rez operator simbol_operator (lista_parametri) ;
class IdClasa { class IdClasa {
};
IdClasa& operator ++ () ; IdClasa& operator ++ (int n) ;
tip_rez operator simbol_operator (lista_parametri) {
}; };
}
n cu funcție prieten n cu funcție prieten
class IdClasa { class IdClasa {
n Numărul de parametri este egal cu aritatea operatorului.
IdClasa& operator ++ (IdClasa &ob) ; IdClasa& operator ++ (IdClasa &ob, int n) ;
n Primul operand este obiectul curent pentru care se apelează
operatorul }; };

Clase si funcții friend. Supraîncărcarea operatorilor 18 Clase si funcții friend. Supraîncărcarea operatorilor 20
Supraîncărcarea operatorilor ++ și -- Supraîncărcarea operatorului =
class Complex { Complex& operator --(Complex& z){
private: z.re -=1;
float re; printf("predecremntare\n");
float im;
}
return z; n Dacă o clasă nu are supraîncărcat operatorul egal
public:
Complex (float re=0, float im=0);
Complex& operator --(Complex& z, int n){
z.re -=1; atunci compilatorul va genera o supraîncarcare
void afisare(); printf("postdecrementare\n");
Complex& operator ++();
Complex& operator ++(int); }
return z; standard care va realiza copierea bit cu bit a datelor
friend Complex& operator --(Complex& z);
friend Complex& operator --(Complex& z,int n);
int main(){
Complex z(4,5);
membru
z.afisare();
}; ++z; z.afisare();
z++; z.afisare();
n Dacă o clasă conține date membru obiecte ale altor
Complex& Complex::operator ++(){
re +=1;
--z; z.afisare();
z--; z.afisare(); OUTPUT clase și nu are supraîncărcat operatorul =, atunci
printf("preincrementare\n"); }

}
return *this; 4+5*i
preincrementare
constructorul generat de compilator va apela la
Complex& Complex::operator ++(int n){
5+5*i
postincrementare supraîncarcarile operatorului = pentru copierea
re +=1; 6+5*i
printf("postincrementare\n");
return *this;
predecremntare
5+5*i
obiectelor membru
} postdecrementare
4+5*i

Clase si funcții friend. Supraîncărcarea operatorilor 21 Clase si funcții friend. Supraîncărcarea operatorilor 23

Supraîncărcarea operatorului = Exemplu I: Supraîncărcarea operatorului =


class Complex { void Complex::afisare(){
n Operatorul = se supraîncarcă numai cu funcție membru private: printf("%-g%+g*i\n", re, im);
class IdClasa { float re;
float im;
}
Complex& Complex::operator = (const Complex &z){
IdClasa& operator = (const IdClasa &ob) ; public:
Complex (float re = 0, float im = 0);
if ( this != &z){
this->re = z.re;
}; Complex (const Complex &z);
void afisare(); }
this->im = z.im;

IdClasa& IdClasa::operator = (const IdClasa &ob) { printf("Apel supraincarcare =\n");


Complex& operator = (const Complex& z); return *this;
if (this != &ob){ // test pentru a evita atribuiri de tipul ob = ob }; }
int main(){
//instructiuni de copiere a datelor membru Complex::Complex (float re, float im){ Complex z1(3,4);
} this->re = re;
this->im = im;
Complex z2=z1;//Apel constructor de copiere
z2.afisare();
return *this; }
Complex::Complex (const Complex &z){
Complex z3;
z3=z1;//Apel supraincarcare =
} this->re = z.re;
this->im = z.im;
z3.afisare();
getch();
printf("Apel constructor de copiere\n"); }
}

Clase si funcții friend. Supraîncărcarea operatorilor 22 Clase si funcții friend. Supraîncărcarea operatorilor 24
Exemplu II: Supraîncărcarea operatorului = Exemplu III: Supraîncărcarea operatorului =
class Persoana {
class Persoana { ~Persoana(){ . . .
private: cout<<"Distrug obiectul:"<<nume<<endl; public:
char *nume; delete nume; . . . OUTPUT
int varsta; } Persoana& operator =(const Persoana &ob){ Apel constructor cu parametri
if (this != &ob){ Apel constructor de copiere
setNume(ob.nume); Apel constructor cu parametri
public: void setNume(char *n){
setVarsta(ob.varsta); Apel supraincarcare =
Persoana(char *n="", int v=0){ if(strlen(nume)<strlen(n)){
} Nume:Misu
nume = new char[strlen(n)+1]; delete nume;
cout<<"Apel supraincarcare = \n"; Varsta:21
strcpy(nume, n); nume = new char[strlen(n)+1];
return *this; Nume:Mihai
varsta = v; }
} Varsta:21
cout<<"Apel constructor strcpy(nume, n);
}; Nume:Mihai
cu parametri\n"; }
Varsta:21
} int main(){ Distrug obiectul:Mihai
void setVarsta(int v){ Persoana p1("Mihai",21); Distrug obiectul:Mihai
Persoana(const Persoana &p){ varsta = v; Persoana p2=p1; Distrug obiectul:Misu
nume = new char[strlen(p.nume)+1]; } Persoana p3;
strcpy(nume, p.nume); p3 = p1;
varsta = p.varsta; void afisare(){ p1.setNume("Misu");
cout<<"Apel constructor de copiere\n"; cout<<"Nume:"<<nume<<endl; p1.afisare();
} cout<<"Varsta:"<<varsta<<endl; p2.afisare();
} p3.afisare();
}; }

Clase si funcții friend. Supraîncărcarea operatorilor 25 Clase si funcții friend. Supraîncărcarea operatorilor 27

Exemplu II: Supraîncărcarea operatorului = Temă


int main(){
Persoana p1("Mihai",21);
OUTPUT
Apel constructor cu parametri
n Implementați clasa Polinom pentru care
Persoana p2=p1;
Persoana p3;
p3 = p1;
Apel constructor de copiere
Apel constructor cu parametri
Nume:Misu
supraîncărcați operatori +, * pentru a efectua
p1.setNume("Misu");
p1.afisare();
p2.afisare();
Varsta:21
Nume:Mihai
Varsta:21
adunarea și înmulțirea a doi vectori
p3.afisare(); Nume:Misu (Corect ar fi fost Mihai)
} Varsta:21
Distrug obiectul:Misu
n Implementați clasa Matrice reprezentată sub
Distrug obiectul:Mihai
Distrug obiectul:Ŕ☼ó forma unui tablou unidimensional alocat
dinamic. Supraîncărcați operatori + (suma),*
(produs).

Clase si funcții friend. Supraîncărcarea operatorilor 26 Clase si funcții friend. Supraîncărcarea operatorilor 28

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