Problema
care se pune aici este cand preferam (daca nu cumva suntem chiar obligati)
sa definim o functie ca membru si cand ca globala ?
Teoria
generala privitoare la clase & obiecte zice ca interiorul unui obiect
este format din:
- In primul rand este vorba de functiile care implementeaza operatii intre obiecte ale unor clase diferite, sau intre obiecte ale unei clase si valori apartinand unor tipuri primare. Aici sunt vizate de fapt functiile-operator. Acest caz este prezentat pe larg in Lucrarea 4 - Supraincarcarea Functiilor si a Operatorilor.
- Presupunem ca avem 2 clase: Vector si Matrice; daca dorim sa implementam operatia de
inmultire a 2 matrici astfel incat sa acoperim si cazul particular al inmultirii intre un vector si o matrice, alegand varianta cu functii membru, ar trebui sa definim in ambele clase cate o functie corespunzatoare; alegand varianta cu functie globala, putem avea o singura functie de inmultire, si anume:Matrice inmultire(const Matrice &m1,const Matrice &m2) {
}//in loc de numele inmultire puteam folosi operator*
//(vezi Lucrarea 4 - Supraincarcarea Functiilor si a Operatorilor)
//. . .
Prevazand in clasa Matrice un constructor cu parametru de tip Vector&, vom putea efectua operatia de inmultire pentru toate combinatiile de operanzi. Din motive de optimizare vom da functiei statut de friend in clasa Matrice, astfel incat sa se evite accesul la datele obiectelor m1 si m2 via apeluri de genul getElem(i,j).
Tot in lista "motivelor obiective" de care aminteam la inceput, ar fi de mentionat si unul (care de fapt e mai putin obiectiv) legat de preferinta programatorilor pentru o notatie sau alta.
Considerand tot clasa Matrice, presupunem ca vrem sa definim o operatie de determinare a inversei unei matrici. Daca denumim aceasta operatie inversa, avem urmatoarele alternative:-ca functie membru, apelul ei s-ar face probabil la modul m.inversa(), aceasta notatie sugerand ca in urma executiei obiectul m va contine inversa valorii sale anterioare (desi nu e obligatoriu sa se intample asa);
In acest caz, alegerea poate fi dictata de preferintele pentru una sau alta dintre notatii.
-ca functie globala, apelul ar fi inversa(m), aceasta notatie sugerand ca m nu se modifica, ci functia creaza un nou obiect care sa contina inversa lui m.
In fine, exista situatii in care utilizarea functiilor friend permite exprimarea unor operatii intr-o notatie mai naturala. Consideram ca avem o clasa Rational care modeleaza lucrul cu numere rationale si presupunem ca este necesara o functie care sa returneze maximul dintre 2 numere rationale. Daca q1 si q2 sunt obiectele pentru care se aplica functia, este evident ca apelul q1.Maxim(q2), corespunzator variantei in care Maxim este functie membru, arata cam "contra naturii" fata de Maxim(q1,q2).