====== Przeładowanie operatorów ( C++ ) ======

Przeładowanie operatorów w klasie sprawia, że posługiwanie się nią jest tak naturalne jak typem wbudowanym.

Przeładowanie operatora dokonuje się definiując funkcję która
      *nazywa się **operator@**  gdzie //@// oznacza symbol operatora (np //+//, //-//, //*//)
      *jako conajmniej jeden z argumentów przyjmuje obiekt danej klasy (nie wskaźnik)


====== Nie można przeładowywać =====

      * **.**     odniesienie do składnika klasy
      * **.***    wybór składnika wskaźnikiem
      * **::**    określenie zakresu

Do grupy tej można jeszcze dodać operator **?:**

====== O czym należy pamiętać ======

      * nie wolno wymyślać operatorów
      * nie można zmieniać ustalonych priorytetów, łączności oraz argumentowości
      * przynajmniej jeden z argumentów operatora musi być typu zdefiniowanego przez programistę

Ten sam operator można przeładowywać wielokrotnie (podobnie jak funkcję) zmieniając zestaw argumentów na których operuje.


====== Sposoby przeciążenia ======

Operator (funkcja operatorowa) może być zdefiniowany jako 
      *niestatyczna funkcja składowa klasy
      *funkcja globalna

Aby umożliwić operatorowi dostęp zarówno do publicznych jak i prywatnych składowych klasy musi on zostać zdefiniowany jako funkcja składowa lub globalna funkcja zaprzyjaźniona z klasą.

Następujące operatory musza zostać zdefiniowane jako niestatyczne funkcje składowe:

 ** = **     ** [] **      ** () **     ** -> **


====== Operatory generowane automatycznie ======

Operatory generowane automatycznie dla każdej klasy:
**=**  **&**  **,**  **new**  **delete**

Jeśli operator ma wykonywać akcję inna niż predefiniowana, należy zdefiniować własną wersję tego operatora.

Operator //=// nie bedzie generowany automatycznie w klasie jesli:
      *posiada ona składnik //const// lub składnik będący //referencją//
      *klasa posiada składową będącą obiektem innej klasy w której operator //=// jest //private//
      *klasa dziedziczy z klasy w której operator //=// jest typu //private//


====== Wyjątkowy operator ======

Operatory inkrementacji (dekrementacji).

Mimo, że są to operatory //jednoargumentowe//, możliwa jest również ich definicja jako operatorów //dwuargumentowych// (próba definicji operatora jednoargumentowego np. //!// jako dwuargumentowego byłaby błędem).

     obiekt.operator++() 	//pre-inkrementacja
     obiekt.operator++(0)	//post-inkrementacja


====== Uwagi ======

Jeśli przeładowano operator ** + ** i ** = ** nie oznacza to, że dostępne są operatory ** += ** albo ** ++**. Są to zupełnie inne funkcje operatorowe i muszą zostać zdefiniowane osobno.

Jeśli dla typów wbudowanych poniższe wyrażenia są równoważne 
	a = a + 1	a +=1	a++
to dobrą praktyką jest trzymanie sie tej konwencji w definiowanych klasach.

Jeśli operator nie zmienia wartości typu wbudowanego, nie powinien też modyfikować wartości obiektów klasy dla której został przeładowany (np. operator **-**).

Przeładowywany operator powinien zwracać wartość. Dzieki temu możliwe będzie budowanie wyrażeń kaskadowych.

Jeśli operator zmienia w jakiś sposócb obiekt, na którym pracuje to powinien być zdefiniowany jako funkcja składowa klasy (zwracająca //l-wartość//). W przeciwnym wypadku (brak modyfikacji składowych obiektu) stosuje się raczej operator w postaci funkcji globalnej.

====== Przykład praktycznego zastosowania przeładowania operatora ======

Rozważmy zapis: 
      int i = 19;
      cout << i;

Dlaczego ten zapis powoduje wyprowadzenie na ekran wartości zmiennej //i// (dwuargumentowy operator //<<// dla typu wbudowanego //int// jest operatorem przesunięcia bitów) ?

Mamy tu doczynienia z przeładowaniem operatora //<<// w klasie //ostream//. Oczywiście jest kilka wersji przeładowania operatora //<<// na okoliczność pracy z różnymi typami argumentów np. //float//, //char*//. Dzięki temu że funkcja operatorowa nie musi być zaprzyjaźniona z klasą można zdefiniować koleją wersję operatora //<<//, w której pierwszym argumentem jest obiekt klasy //ostream// (brak jednak dostępu do niepublicznych składników), a drugim obiekt definiowanej klasy. 

Funkcja ta nie może być funkcją składową klasy //ostream//, ponieważ nie można modyfikowac wnętrza klas bibliotecznych.

Są więc dwie inne możliwości realizacji tego zadania:
     *funkcja globalna
     *funkcja składowa definiowanej klasy

Ponieważ zapis
      w << cout;
wyglada bardzo dziwacznie ta druga możliwość odpada.

Jeśli definiując funkcję operatorową //<<// jako funkcję globalną wymagany jest dostęp do niepublicznych składowych klasy, musi ona zadeklarować przyjaźń z naszą funkcją operatorową.

===== Linki =====
  * http://nauka-programowania.pl/O2.PDF

