Sunteți pe pagina 1din 7

Funcții friend

Clase și 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

Exemplu – Necesitatea accesării datelor protejate Funcții friend globale


class Punct {
private: n Declararea unei funcții friend globale pentru o clasă se face
double x, y; incluzând prototipul ei, precedat de cuvântul cheie friend, în
public:
Punct(double x=0, double y=0){ inaccesibile acea clasă
this -> x = x; class IdClasa {
this -> y = y;
} friend tip_ret id_functie_prieten(lista_de_parametri);
};
};
n Definiţia funcţiei se face în afara clasei
double distanta(Punct p1, Punct p2) {
tip_ret id_functie_prieten(lista_de_parametri) {
return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
} //corpul de instructiuni în care avem acces la datele/metodele protejate ale obiectelor clasei IdClasa
}

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 Exemplu: Funcții friend membre ale altor clase
class Punct { class Punct; PoligonConvex::PoligonConvex(int n, Punct v[]){
Funcția distanta este declarată this -> n = n;
private:
double x, y; funcție prieten a clasei Punct class PoligonConvex{ varfuri = new Punct[n];
public: Punct *varfuri; for (int i=0;i<n;i++){ Definiția funcției afiseaza.
Punct(double x=0, double y=0){ int n; varfuri[i] = v[i]; Avem acces asupra datelor
this -> x = x; public: } private x și y din 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<<")";
int main(){ friend void PoligonConvex::afiseaza(); }
Punct p1(1,0), p2(4,4); }; cout<<"]";
cout<<"distanta="<< distanta (p1,p2); }
getch(); Definiția funcției distanta. Punct::Punct(double x, double y){
} Avem acces asupra datelor this -> x = x; int main(){
private x și y din clasa Punct this -> y = y; Punct t[3]={Punct(0,0), Punct(3,0),
} Punct(3,4)};
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)


Sunt funcţii membre ale unei clase ce au acces la datele membru protejate ale
n
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/funcţiilor membre protejate ale
cheie friend, în clasa în care se dorește accesul
class IdClasaA; //declarare a clasei IdClasaA înaintea definirii clasei IdClasaB
unei alte clase IdClasaA atunci declarăm clasa IdClasaB ca fiind
class IdClasaB { clasă 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();
Segment::Segment (Punct o, Punct v){
this -> o = o; n Un tip de date (predefinit) definește un set de
public: this -> v = v;
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<<"[";
scădere (-), 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 ¨ asociativitatea
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){
Supraîncărcare cu
n Sintaxa carora acționează operatorul)
private:
float re;
float im;
funcţii membru
Complex rez;
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 {
IdClasa& operator ++ (IdClasa &ob) ; IdClasa& operator ++ (IdClasa &ob, int n) ;
n Numărul de parametri este egal cu aritatea }; };
operatorului.

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 automat o
void afisare(); printf("postdecrementare\n");
Complex& operator ++();
Complex& operator ++(int); }
return z; supraîncărcare standard care va realiza copierea bit
friend Complex& operator --(Complex& z);
friend Complex& operator --(Complex& z,int n);
int main(){
Complex z(4,5);
cu bit a datelor 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încărcările operatorului = pentru copierea
re +=1;
printf("postincrementare\n");
return *this;
6+5*i
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); this->im = z.im;
void afisare(); }
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; z3.afisare();
this->im = z.im; 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 cu parametri\n"; strcpy(nume, n);
}; Nume:Mihai
} } Varsta:21
int main(){ Distrug obiectul:Mihai
Persoana(const Persoana &p){ void setVarsta(int v){ Persoana p1("Mihai",21); Distrug obiectul:Mihai
nume = new char[strlen(p.nume)+1]; varsta = v; Persoana p2=p1; Distrug obiectul:Misu
strcpy(nume, p.nume); } Persoana p3;
varsta = p.varsta; p3 = p1;
cout<<"Apel constructor de copiere\n"; void afisare(){ p1.setNume("Misu");
} 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
n Implementați clasa Matrice reprezentată sub
p3.afisare(); Nume:Misu (Corect ar fi fost Mihai)
} Varsta:21
Distrug obiectul:Misu
Distrug obiectul:Mihai
Distrug obiectul:Ŕ☼ó forma unui tablou unidimensional alocat
dinamic. Supraîncărcați operatori + (suma),*
(produs), = (atribuire), [] (accesul la elemente
matricei).
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