Supraincarcarea operatorilor



    Supraincarcarea (supradefinirea, termenul overloading) operatorilor permite atribuirea de noi semnificatii  operatorilor uzuali (operatorilor intalniti pentru tipurile de date predefinite). Asa cum am subliniat in numeroase randuri, clasa reprezinta un tip de date (o multime de valori pentru care s-a adoptat un anumit mod de reprezentare si o multime de operatii care pot fi aplicate acestora).

   Astfel, operatorul + foloseste la adunarea a doua date de tip int, float sau double, insa aceluiasi operator i se poate atribui semnificatia de "alipire" a doua obiecte de tipul sir, sau de adunare a doua obiecte de tipul complex,  vector sau matrice.

   Observatie: Operatorii sunt deja supradefiniti pentru a putea opera asupra mai multor tipuri de baza (de exemplu, operatorul + admite operanzi de tip int, dar si float sau double), sau pot avea semnificatii diferite (de exemplu, operatorul * poate fi folosit pentru inmultirea a doi operanzi numerici sau ca operator de deferentiere, operatorul >> poate avea semnificatia de operator extractor sau operator de deplasare pe biti).

   Prin supraincarcarea operatorilor, operatiile care pot fi executate asupra instantelor (obiectelor) unei clase pot fi folosite ca si in cazul tipurilor de date predefinite.

Deci, limbajul C++ permite supradefinirea operatorului op prin definirea unei functii numite operator op

Unde op este un operator ca : +, -, [] , & etc.

Supradefinirea se realizeaza astfel:

tip_val_intoarsa operator op (lista_declar_parametri)
{
// . . . .   corpul functiei
}

     Restrictii la supraincarcarea operatorilor
Supraincarcarea operatorilor este supusa urmatoarelor restrictii:
- Se pot supraincarca doar operatorii existenti; nu se pot crea noi operatori.
- Nu se poate modifica aritatea (numarul de operanzi) operatorilor limbajului (operatorii unari nu pot fi supraincarcati ca operatori binari, si invers).
- Nu se poate modifica precedenta si asociativitatea operatorilor.
- Nu pot fi supraincarcati operatorii   .   ::?  si  :

Observatie: Daca operatorul = nu este supraincarcat, el are o semnificatie implicita.

Exemplul 1:  Pentru clasa complex , putem atribui operatorului + semnificatia: expresia a+b (a, b sunt obiecte din clasa complex) reprezinta "suma" a doua numere complexe si este un numar complex. Astfel, supradefinirea operatorului + consta in definrea unei functii cu numele: operator +
 

   Supraincarcarea operatorului +

#include<iostream.h>

#include<conio.h>

 

class complex

{public:

  float x,y;

 

void display()

   {cout<<x<<"+"<<y<<"*i";

    cout<<endl;

   }

 

complex operator+(complex z)

  {complex s;

   s.x=x+z.x;

   s.y=y+z.y;

   return s;

   }

 

};

 

 

void main()

{clrscr();

 complex a,b,aux;

 cout<<"primul numar "<<endl;

 cout<<"partea reala ";

 cin>>a.x;

 cout<<"partea imaginara ";

 cin>>a.y;

 cout<<"al doilea numar "<<endl;

 cout<<"partea reala ";

 cin>>b.x;

 cout<<"partea imaginara ";

 cin>>b.y;

 aux=a+b;

 cout<<endl<<"Suma celor doua numere "<<endl;

 aux.display();

 cout<<endl;

 cout<<"primul numar"<<endl;

 a.display();

 cout<<endl<<"al doilea numar "<<endl;

 b.display();

 a=a+b;

 cout<<endl<<"primul numar trece in suma celor doua:"<<endl;

 a.display();

 cout<<"cel de al doilea numar ramane neschimbat "<<endl;

 b.display();

 getch();

}

Exercitii propuse: 
Sa se supraincarce operatorii: -, *, / pentru clasa complex  

Exemplul 2: Supraincarcarea operatorului unar ! se poate utiliza de exemplu pentru a obtine conjugata unui numar complex:

complex operator!()

      {complex c;

       c.x=x;

       c.y=-y;

       return c;

       }

 

Apelul se va face astfel:
b=!b;

Sau :

complex q;

q=!b;

Exercitiu propus:
1.
Sa se defineasca o clasa vector care sa contina o metoda de afisare. Sa se determine suma a doi vectori fara a se supraincarca nici un operator.

2. Aceeasi problema sa se rezolve prin supratncarcarea operatorului + si []

Supraincarcarea operatorului de indexare
    Operatorul de indexare este un operator binar si are forma generala:

Tip_vector &  operator[](lista_parametri) { prelucrari;

Exemplul 3:                                                      }

#include<iostream.h>

#include<conio.h>

 

class vector

  {public:

   float v[20];

   int n;

 

   float & operator[](int i)  //supraincarcarea operatorului []

   {return v[i];}

 

    vector operator+(vector u);

 

   void afisare();

  };

 

void vector::afisare()

 {for(int i=1;i<=n;i++)

    cout<<v[i]<<" ";

  cout<<endl;

 }

 

vector vector::operator+(vector u)

{vector rez;

 rez.n=n;

 for(int i=1;i<=n;i++)

    rez.v[i]=v[i]+u.v[i];

 return rez;

}

 

 

 void main()

 {clrscr();

  vector a,b;

  cout<<"nr de elemente  ";

  cin>>a.n;

  for(int i=1;i<=a.n;i++)

    cin>>a[i];

  cout<<endl;

  cout<<"al doilea vector ";

  b.n=a.n;

  for( i=1;i<=b.n;i++)

    cin>>b[i];

  cout<<endl;

  cout<<"cei doi vectori sunt "<<endl;

  a.afisare();

  cout<<endl;

  b.afisare();

  vector c;

  c=a+b;

  cout<<endl<<"suma "<<endl;

  c.afisare();

  getch();

 }

 

Exemplul 4:

In mod similar se incarca operatorul ( ) in scopul prelucrarii matricilor:

 

class matrice

   {public:

     int a[20][20],nl, nc;

     int & operator ( ) (int i,int j)

            {return a[i][j]; }

 

    }

 

Fie matrice m   o instanta a clasei complex. Atunci prelucrarea componentei de pe linia 2 si coloana 3 in scopul atribuirii valorii 50 se va face :

m(2,3)=50 ;

 

Exercitiu propus:

Sa se completeze clasa matrice cu metoda de afisare si sa se supraincarce operatorul +. Sa se determine suma a doua matrici.