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

рассказать друзьям и получить подарок

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Translate Переводчик

Подписка на новости

SmartResponder.ru
Ваш e-mail: *
Ваше имя: *

Хостинг для Wordpress сайтов