sâmbătă, 1 martie 2008

Polimorfism si suprascrierea operatorilor

Transmiterea parametrilor prin referinta: daca in C trebuia sa transmitem adresa variabilei pentru a putea sa ii schimbam valoarea, in C++ putem transmite parametrii prin referinta folosind operatorul &.

int functie(int &a,int b)
{
b=a; //la iesirea din functie b va avea aceeasi valoarea, chiar daca am facut o atribuire
a=b+5; // a va avea valoarea schimbata pentru ca a fost transmis prin referinta
}

Polimorfism in C++: putem folosi acelasi nume de functie pentru a realiza mai multe actiuni - trebuie sa difere numarul parametrilor sau tipul parametrilor (cred). Daca difera doar tipul returnat, sau daca difera tipul parametrilor la modul ca intr-o parte avem int iar in alta parte double compilatorul va genera erori. Atentie la functiile cu parametri impliciti.

Functii cu parametri impliciti:

int clasa_mea::functie(int a, int b=0)
{
this->a = a;
this->b = b;
}
...
obiect.functie(5,3); //obiect.a va lua valoarea 5 iar b valoarea 3
obiect.functie(5); //daca nu specificam al doilea parametru aceasta va primi valoarea implicita specificata la implementare

Sa presupunem ca pe langa functia de mai sus definim inca una cu un singur parametru:

int clasa_mea::functie(int a)
{
this->a = a;
this->b = 500;
}

In momentul in care apelam obiect.functie(5) programul nu va sti care dintre cele doua implementari trebuie sa o apeleze => bad polymorphism.

Operatorii din C/C++ sunt functii deci pot si suprascrisi:

class clasa_mea
{
...
clasa_mea operator +(alta_clasa b)
{
//operatii smechere scrise inline din lene
}
};

Operatorul + cu un singur operand? Si cum il apelam? Restul metodelor le apelam obiect.functie(); deci pentru functie() aveam o structura de date cu care lucram in cadrul ei, chiar daca nu are parametri - instanta care apeleaza operatorul. Deci operatorul + de mai sus are doi parametri: unul de tip clasa_mea, cel care apeleaza functia/operatorul si unul de tip alta_clasa.
Operatorul il apelam cum am apela orice alt operator:

clasa_mea a;
alta_clasa b;
clasa_mea c=a+b;

Dar 1. daca respectam incapsularea, membrii variabile vor fi privati 2. cum fac pentru comutativitate? Daca scriem ca mai sus primul parametru va fi intotdeauna de tipul clasa_mea; daca vreau sa fac alta_clasa+clasa_mea. Daca alta clasa este definita de mine nu voi avea acces la membrii privati din clasa_mea. Daca alta_clasa este un tip din C++ cum fac?

Putem scrie o functie care nu face parte din nici o clasa, in felul acesta putem specifica ce ordine vrem pentru operatori:

clasa_mea operator+(clasa_mea a, alta_clasa b){...}

Insa si asa vom avea probleme cu membrii privati. Pentru asta folosim specificatorul friend:

class clasa_mea
{
...
friend clasa_mea operator +(clasa_mea a,alta_clasa b)
{
//operatii smechere scrise inline din lene
}
};


Acesta ii spune clasei ca operatorul + nu face parte din clasa_mea, insa ii poate accesa membrii privati. Poate fi folosit pentru orice functii, nu neaparat pentru operatori (cred ca merge si pentru membri ai altor clase - daca vrei sa faceti programe ciudate).

Cand suprascriem operatori trebuie sa respectam numarul parametrilor.

cin si cout (de fapt >> si <<) sunt operatori (deja suprascrisi chiar, ca pot fi folositi si la shiftarea pe biti) deci pot fi suprascrisi. Sintaxa lor standard este cam asa:

istream& operator >> (istream& cin, int &a){...}
ostream& operator << (ostream& cout, int a){...}

Ar trebui sa returneze ceva?

Niciun comentariu: