5.4. Supra?nc?rcarea operatorilor << ?i >>
5.4. Supra?nc?rcarea operatorilor << ?i >>
Ne-am plictisit s? scriem r?nduri ?i r?nduri de tipul:
cout << "fr12=";
fr12.print();
cout << endl;
Vrem s? avem posibilitatea de a scrie laconic ?i frumos:
cout << "fr12=" << fr12 << endl;
Din fericire, este u?or de transformat acest vis ?n realitate.
Cum a fost spus mai ?nainte, supra?nc?rc?nd orice operator, este de dorit ca semantica operatorului supra?nc?rcat s? fie ?n concordan?? cu semantica ini?ial? a acestui operator. ?ns?, orice regul? are ?i excep?ii. Un bun exemplu de a?a excep?ii reu?ite este supra?nc?rcarea ?n C++ a operatorilor de deplasare a bi?ilor << ?i >> pentru opera?ii de I/O f?cut? ?n fi?ierul antet "iostream.h" pentru tipurile de date de baz? ?i clasele ostream ?i istream destinate pentru crearea stream-urilor capabile s? ob?in?, respectiv, s? introduc? informa?ii. Putem supra?nc?rca ace?ti operatori astfel ca ei s? efectueze opera?ii de I/O asupra claselor noastre.
?n limbajul C++ operatorul << supra?nc?rcat pentru opera?ii de ie?ire se nume?te operator de inser?ie, ?n sens c? el trimite octe?ii (caractere) ?ntr-un ostream, iar operatorul >> supra?nc?rcat pentru opera?ii de ie?ire se nume?te operator de extragere, ?n sens c? el ob?ine octe?ii (caractere) dintr-un istream. Utilizatorul supra?ncarc? operatorii de inser?ie ?i de extragere prin func?ii nemembre, de obicei, totu?i prietene ale clasei pentru care va fi folosit operatorul respectiv.
Forma general? de supra?nc?rcare a unui operator de inser?ie este urm?toarea:
ostream &operator<<(ostream &stream, tip_clas? obiect)
{ // codul func?iei de inser?ie … return stream; } sau ostream &operator<<(ostream &stream, const tip_clas? &obiect) { // codul func?iei de inser?ie … return stream; } |
Primul operand aici este o referin?? spre un ostream care va fi ?i ?ntoars? ca rezultat al opera?iei, ceea ce ne va da posibilitatea de a ?nl?n?ui operatorii de inser?ie.
Ca exemplu, supra?nc?rc?m operatorul de inser?ie pentru clasa fractie_rationala prin func?ie prieten?.
?n sec?iunea public a clasei noastre inser?m antetul:
friend ostream &operator<<(ostream& stream, const fractie_rationala &fr);
Iar dup? definirea clasei inser?m definirea func?iei:
ostream &operator<<(ostream& stream, const fractie_rationala &fr) { stream << fr.numarat; stream << "/"; stream << fr.numit; return stream; } |
care face practic acela?i lucru ca ?i func?ia membr? print(), numai c? pentru orice ostream, ?i poate fi ?nl?n?uit?.
La func?ia main() ad?ug?m fragmentul:
fractie_rationala fr13(1, 2); cout << "fr13 = " << fr13 << endl; fractie_rationala fr14(2, 5); cout << "fr14 = " << fr14 << endl; cout << fr13 << " + "<< fr14 << " = " << (fr13+fr14) << endl; Acest fragment va afi?a: fr13 = 1/2 fr14 = 2/5 1/2 + 2/5 = 9/10 |
S? ?inem seama de luarea ?n paranteze a expresiei (fr13+fr14). Mai subliniem c? ?i operatorul << supra?nc?rcat poate fi scris ?n form? de func?ie. De exemplu, instruc?iunea:
cout << "fr13 = " << fr13 << endl;
poate fi scris? ?i astfel:
operator<<(cout << "fr13 = ", fr13) << endl;
Func?ia print() membr? a clasei fractie_rationala poate fi supra?nc?rcat? pentru orice ostream, de exemplu, astfel:
ostream &print(ostream &stream) { stream << numarat << '/' << numit; return stream; } Cu apelurile de tipul: cout << "fr13 = "; fr13.print(cout); cout << endl; cout << "fr14 = "; fr14.print(cout); cout << endl; fr13.print(cout); cout << " + "; fr14.print(cout); cout << " = "; (fr13+fr14).print(cout); cout << endl; |
Aceasta versiune supra?nc?rcat? a func?iei print() poate fi folosit? la supra?nc?rcarea operatorului de inser?ie pentru clasa fractie_rationala prin func?ie care poate ?i s? nu fie prieten?, de exemplu, astfel:
ostream &operator<<(ostream& stream, const fractie_rationala &fr) { return fr.print(stream); } |
Rezultatul va fi acela?i ca ?i pentru func?ia prieten?.
?n exemplele ulterioare, pentru afi?area obiectelor ?n majoritatea de cazuri vom folosi operatorul << supra?nc?rcat, ?ns? func?ia membr? print() o vom l?sa totu?i ?n clasa fractie_rationala.
Forma general? de supra?nc?rcare a unui operator de extragere este urm?toarea:
istream &operator>>(istream &stream, tip_clas? &obiect)
{ // codul func?iei de extragere … return stream; } |
Primul operand aici este o referin?? spre un istream care va fi ?ntoars? ca rezultat al opera?iei, ceea ce ne va da posibilitatea de a ?nl?n?ui operatorii de extragere. Parametrul doi numaidec?t se transmite prin referin??, fiindc? obiectul ??i va schima con?inutul.
Ca exemplu, supra?nc?rc?m operatorul de extragere pentru clasa fractie_rationala prin func?ie prieten?.
?n sec?iunea public a clasei noastre inser?m antetul:
friend istream &operator>>(istream& stream, fractie_rationala &fr);
Iar dup? definirea clasei inser?m definirea func?iei:
istream &operator>>(istream& stream, fractie_rationala &fr) { char str[50]; stream >> str; fr.numarat=0; int i=-1; while(str[++i]!='/') fr.numarat = fr.numarat*10 + str[i]-'0'; fr.numit=0; while(str[++i]) fr.numit = fr.numit*10 + str[i]-'0'; return stream; } |
care asigur? nu numai introducerea datelor, dar ?i ?nl?n?uirea operatorilor >>. Pentru verificare, ad?ug?m la func?ia main() urm?torul fragment:
fractie_rationala fr15; cout << "Introdu o fractie: "; cin >> fr15; fractie_rationala fr16; cout << "Mai introdu inca o fractie: "; cin >> fr16; cout << "fr15 = " << fr15 << endl; cout << "fr16 = " << fr16 << endl; cout << "fr15 + fr16 = " << (fr15+fr16) << endl; cout << "Introdu inca doua fractii prin spatiu: "; cin >> fr15 >> fr16; cout << fr15 << " + " << fr16 << " = " << (fr15+fr16) <<endl; |
La executarea acestui fragment va trebui s? introducem frac?ii de la tastatur?. Rezultatul va fi aproximativ urm?torul:
Introdu o fractie: 3/10 Mai introdu inca o fractie: 5/10 fr15 = 3/10 fr16 = 5/10 fr15 + fr16 = 4/5 Introdu inca doua fractii prin spatiu: 1/7 3/7 1/7 + 3/7 = 4/7 |
Exist? ?i alt? posibilitate. Putem insera ?n clasa fractie_rationala o func?ie membr? public? pentru introducerea din orice istream, de exemplu, astfel:
istream &input(istream &stream) { char c; stream >> numarat >> c >> numit; return stream; } |
Apoi folosim aceast? func?ie la supra?nc?rcarea operatorului de extragere >> prin func?ia care poate ?i s? nu fie prieten? a clasei noastre:
istream &operator>>(istream& stream, fractie_rationala &fr) { return fr.input(stream); } |
Rezultatul va fi acela?i ca ?i pentru func?ia prieten?.
_________________________
Autorul: dr.conf. S. Pereteatcu
Оставить комментарий