Sunteți pe pagina 1din 10

Operatori – Boja

Ca sa scapam de niste probleme fara sa realizam mai bine initializam cu 0 sau NULL cand
definim atributele in clasa, in caz ca uitam de constr fara param.
//Punem aceeasi semnatura si in friend ca altfel nu gaseste un corespondent.

Operator <<
Main: cout << mesaj1; //se incarca global pentru ca are ca prim parametru cout
Daca primul operator este de tipul clasei pot incarca prin functie membra, deoarece acel
parametru intra in functia respectiva prin this.

void operator<<(ostream& consola, Mesaj m)


//retinem ca orice functie care primeste prin valoare un obiect va apela constructorul de copiere
(mai exact la: Mesaj m)
//dar e mai safe cu &

Se poate face si citirea fara friend daca avem get-uri (interfata publica)!! Cand folosim get-eri
punem paranteze (): m.getPrioritate();

Ce e void la operatori? Inseamna ca nu trebuie sa intoarca nimic. Si apare o problema: ca vreau


sa afisez in cascada (mai multe obiecte pe aceeasi linie).

Cout << mesaj3 << mesaj2;


//expresia se executa de la stanga la dreapta
//aici sunt 2 functii apelate, prima: cout << mesaj3 si a 2-a: (cout << mesaj3) << mesaj2;
//asta inseamna ca dupa ce s-a executat (cout << mesaj3) intoarce void si ajung in situatia:
void << mesaj2;
//daca vrem sa permitem punem tip retunat tipul clasei: ostream
//returnam tipul de care are nevoie operatorul nostrum, adica ostream& operator<<
//si return consola;
Operatorul =
mesaj3=mesaj2; //e apelat atunci cand nu avem definire (gen: Mesaj mesaj2 = mesaj3, adica aici
definim mesaj2)

//se incarca mereu prin functie membra!!


//implicit ce e la stanga ar trebui sa fie reprezentat printr-o adresa si sa se modifice si ma forteaza
cumva ca ce e la stanga sa gestionez printr-un pointer, deoarece fiind functie membra, variabila
de la stanga intra prin pointerul this in functie
//se apeleaza constructorul de copier, deoarece primim mesajul de la dreapta prin valoare si
constr de copier se apeleaza pentru a face o copie a mesajului mesaj1 pe stiva functiei = (adica in
mesaj)
//this e obiectul care se modifica mereu!!

//daca vreau sa fac un egal in cascada: mesaj3=mesaj2=mesaj1;


//expresia se executa de la dreapta la stanga
//aici sunt 2 functii apelate, prima: mesaj2=mesaj1 si a 2-a: mesaj3=(mesaj2=mesaj1);
//a 2-a intoarce void daca nu pun in cascada si tipul returnat Mesaj
//si fie returnam mesajul initial (Mesaj mesaj), fie retunam mesajul modificat, adica
*this(valoarea indicata la adresa unui pointer);

Pentru return void operatorul nu se poate apela in cascada!


Operatori binar (cu 2 operanzi): + - / * //sursa nu se modifica niciodata
//rezultat=sursa1+sursa2;
//NU MODIFICA VALOAREA OPERANZILOR (sursa1 sau sursa2)

Operatorul +
1. Main:
mesaj2=mesaj1 + “completare”;//obiect + ceva
//pentru ca primul parametru e de tip mesaj, pot merge prin functie membra, ca sa scap de friend
Mesaj operator+(string msg){ //nu mai scriu primul parametru ca e de tip mesaj(this)
//nu putem pune void, pt ca avem eroare de compilare! (nu exista operator care sa aiba la stanga
Mesaj si la dreapta void, deci avem nevoie ca tipul returnat sa fie Mesaj)
//aici se apeleaza o data constructorul de copiere la Mesaj
//NU MODIFICATI THIS! FACETI COPIE!
Mesaj rezultat=*this; //constructorul de copiere e aici
rezultat.text +=mesaj;
return rezultat;
}
NU MODIFICA VALOAREA OPERANZILOR/PARAMETRILOR !! Care sunt operanzii(sunt
subliniati)?
mesaj2=mesaj1 + “completare”;
//verifici inainte si dupa sa vezi daca modifica ceva

2. Main:
mesaj3= “Am uitat sa adaug” + mesaj2; //string+ obiect
//nu are cum sa fie prin functie membra ca am primul param string
Mesaj operator+(string msg, Mesaj mesaj){ //il pun in clasa prin friend
Mesaj rezultat = mesaj;
//nu putem folosi ca in sem trecut functia + de mai sus pt ca vrem //sa adauge la inceput, nu e
concatenare sa adauge el unde vrea
//nu returnam void ci mesaj
rezultat.text = msg + rezultat.text; //pentru a concatena mesajul msg
inaintea lui text din obiect
return rezultat;
}

3. Main:
Mesaj mesaj4;
mesaj4= mesaj2 + mesaj3//2 obiecte
//merg prin functie membra
Mesaj operator+(Mesaj m2){ //primul parametru este this adica mesaj !!
Mesaj rezultat = *this; //nu modificam this
rezultat.text += m2.text;
//vreau sa concatenez la textul din this(m1) textul din m2
return rezultat;
}

Operatorul *
4. Main: mesaj4=3*mesaj2;
//functie globala ca avem 3 la stanga (int)
Mesaj operator*(int nr, Mesaj mesaj){
//vom replica mesajul de nr ori
//nu modifica this!!
Mesaj rezultat = mesaj;//il copiez pe mesaj pt ca sunt in zona globala si nu exista
this
string textInitial = rezultat.getText();
reultat.text=” ”;//ca sa nu afiseze de 4 ori plecam de la sir vid
for(int i=0; i<nr; i++){
rezultat.text+=textInitial;//nu vrem sa modificam mesaj
}
return rezultat;
}

Sa pot reseta mesajele, pt ca au ajuns la dimensiuni f mari folosim op=


MAIN: mesaj2=”Salut”;
op= nu e obligatoriu intre 2 mesaje
//supraincarcare =
//la stanga mesaj la dreapta string
//ce intoarce ce e scris in main? Il privim ca pe o actiune si deci nu intoarce nimic!! ………
VOID……. <- (mesaj2=”Salut”;)

void operator= (string textMesaj){


this->text=textMesaj;
} //aici am resetat textul

Operatori binari de tipul += -= *= /=


//sunt echivalentul: sursa = sursa + ceva; //de ex +=
//sursa += ceva;
//e clar ca aici se modifica sursa
Main:
mesaj1=”test”;
mesaj2=”hello”;
mesaj1+=”operatori”; //functie membra ca primul parametru este mesaj si al 2-lea string
mesaj2*=4; //functie membra ca primul parametru este mesaj si al 2-lea int

void operator+=(string unText){ // operator+=(Mesaj+=string)


//aici e ok sa modificam this
//am la stanga un obiect care se modifica
this text+=unText;
}

//operator *= (Mesaj *= int)


void operator*=(int repetitii) {
//aleg sa fac acelasi lucru ca si pentru *
//folosesc operatorul * definit anterior
*this = repetitii * (*this);
}

Operatori unari (pt ca au un sigur parametru) ++ -- cu cele 2 forme: post si pre


int vb1=10;
int vb2=vb1++;
// post(dupa) in raport cu egalul, adica cu operatia de la stanga; in raport cu op de la stanga; ++ se
va executa dup ce vb1 a dat valoarea lui lui vb2 si apoi e incrementat;
int vb3=++vb1;
//se returneaza valoarea modificata, dar vb1 se modifica mereu!! Nu scapa, ci conteaza ce
returneaza
Mesaj mesaj5(20,”Mesaj important”);
mesaj1 = mesaj5++;
cout << mesaj1 << mesaj5; //20 si apoi 21
mesaj2=++mesaj5;
cout << mesaj1 << mesaj5; //22 si apoi 22

//functie membra clar

//operator++(Mesaj ++) //intoarce un mesaj //post-incrementare are INT


Mesaj operator++(int) { //e fara parametru ca this intra in mesaj, se modifica this-ul
//int nu foloseste la nimic, dar asa a fost conventia ca sa facem o diferenta intre post si pre
//trebuie sa pastrez valoarea obiectului si sa returnez dupa modificare acea valoare
//pre-incrementare
Mesaj copie = *this;
this->prioritate += 1;
return copie;//modificam this in functie de ce se cere si returnam copia
}

//operator++ (++Mesaj) //intoarce un mesaj //pre incrementare


Mesaj operator++() { //e fara parametru ca this intra in mesaj, se modifica this-ul
//pre-incrementare
this->prioritate += 1;
return *this; //aici putem modifica deja
}
Operatorul ! //intoarce true sau false (NOT)
//facem negatia cu el /putem verifica chestii cu el
//are un singur parametru – nu se pot supraincarca pt ca au un singur nume
//verificam lungimea textului vs 5 caractere
bool operator!() {
if (this->text.size() > 5)
return true;
else
return false;}
MAIN:
if (!mesaj1)
cout << endl << "Textul are mai mult de 5 caractere";
else
cout << endl << "Textul are cel mult 5 caractere";

Operatorul functie()
//folosit ca si cand obiectul este o functie
//cati parametri primeste noi decidem! //e flexibil

MAIN: mesaj2=mesaj1(2,6); //are 3 param: obiectul mesaj, si apoi parametri aia 2 (2 si 6)


//functie membra
Mesaj operator()(string msj, int repetitii) { //intoarce mesaj
Mesaj rezultat = *this; //atentie sa nu modificati this
for (int i = 0; i < repetitii; i++)
rezultat.text += msj;
return rezultat;
}
Operatorul de indexare[]
//da acces citire sau scriere/citire la o colectie interna private
mesaj1=”test”;
cout << endl<<”primul character din mesaj este”<<mesaj1[0];

//operator [] - permite DOAR citirea valorilor (adica sav ad caracterul din text)
//char operator[](int index) { //ce returnam? Un singur character, deci e char
//validam ca sa ne asiguram ca nu crapa:
// if (index >= 0 && index < this->text.size())
// return this->text[index]; //daca e asa returnez caracterul
// else
// throw new exception("indexul este gresit"); //daca nu arunc exceptie
//}

//daca vreau sa modific:


MAIN: mesaj1[0]=”t’; //returnam o variabila, nu un char ca sa modificam
//operator [] - permite citirea si modificarea valorilor
char& operator[](int index) { //returnam variabila caracterului care se gaseste in text la
indexul acela prin &(referinta in loc de valoarea)
if (index >= 0 && index < this->text.size())
return this->text[index];
else
throw new exception("indexul este gresit");
} //aici se intoarce referinta caracterului
E ca si cum as face 5=10; daca nu am &
Operatori conditionali == < > <= >= != (intorc true sau false)
Poate sa fie un nr vs mesaj nu neaparat mesaj vs mesaj.

Operatorul cast (implicit vs explicit)


//cast si intre tipuri diferite de obiecte (int, float, Email)
Cast are un singur parametru - tipul clasei deci functie membra
//tipul la care vrei s afaci conversie e numele operatorului, nu exista numele asta cast
//operator cast la int
//returneaza prioritatea mesajului
//forma implicita - nu scriem explicit (DAR sa evitati)

explicit operator int() { //nu are tip returnat, e implicit numele operatorului cast
return this->prioritate;
}

//forma implicita e periculoasa pt ca spune poate de op+ pe care l-am supraincarcat in diferite
moduri ca sunt mai multi de tipul asta si nu stie ce sa aleaga (ti arata in eroare pe toti).
De exemplu la op+ (mesaj2=mesaj1+”completare”) castul implicit la int e folosit de compilator
fara sa ne intrebe si cumva are prioritate si compilatorul va incerca mereu sa ne duca in tipuri cu
care el stie sa lucreze si e cumva mai usor sa faca cast (se chinuie sa transforme mesaj1 la int).

De aia cast implicit in toate formele sale este de evitat pt ca da peste cap compilatorul. El il va
folosi cu prioritate fara sa te intrebe si ajungem in situatii aberante.

Ca sa evitam folosim forma explicita:


int prioritate=(int)mesaj6;
//deci de aia prefer sa ii spun eu cand sa aleaga cand sa foloseasca cast la int, sa ma astepte pe
mine sa ii spun eu explicit fa cast la int aici.
Si ca sa ii spunem compilatorului sa nu mai foloseasca forma implicita punem explicit in fata.

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