LEKCJA34.TXT

(25 KB) Pobierz
LEKCJA 34 OVERLOADING OPERATOR�W. 
________________________________________________________________ 
Podczas tej lekcji poznasz mo�liwo�ci dostosowania operator�w  
C++ do w�asnego "widzimisi�" i do potrzeb w�asnych obiekt�w.  
________________________________________________________________ 
 
Niemal od pocz�tku niniejszej ksi��ki korzystamy z operator�w  
poddanych overloadingowi. S� to operatory << i >> , kt�re  
pierwotnie wykonywa�y bitowe przesuni�cie w lewo i w prawo.  
Owerloading tych operator�w "za�atwi�" za nas producent  
(Borland, Microsoft, czy inny). Jak widzisz, nie powoduje to w  
dalszym u�ytkowaniu tych operator�w �adnych zauwa�alnych  
komplikacji, a cz�sto u�atwia tworzenie program�w. Zwr�� uwag�,  
�e overloading operator�w (jak i definicje klas) mo�e znajdowa�  
si� w do��czonych plikach nag��wkowych i po jednorazowym  
wykonaniu mo�e by� "niewidoczny" dla programist�w tworz�cych  
programy aplikacyjne. 
 
Je�li projektujemy (definiujemy) now� klas�, dodajemy do C++  
nowy, lecz pe�noprawny typ danych. Autorzy C++ nie byli w stanie 
 
przewidzie� jakie klasy i jakie obiekty mog� wymy�li� kolejne  
pokolenia programist�w w ramach swojej radosnej tw�rczo�ci.  
Wprowadzili zatem do C++ jasne i jednoznaczne algorytmy  
post�powania z typami "typowymi". C++ doskonale wie jak dodawa�, 
 
mno�y�, czy odejmowa� np. liczby int, long, float itp., nie wie  
jednak jak doda� do siebie obiekty klas CString (CString = Class 
 
String = klasa "�a�cuch znak�w"), TOdcinek (to taki kawa�ek  
prostej) itp.. A przecie� mi�o by�oby, gdyby rozbudowa�  
 dzia�anie operator�w tak, by by�o mo�liwe ich typowe  
zastosowanie w stosunku do naszych w�asnych, "nietypowych"  
obiekt�w:  
 
int x, y;     int z = x + y;      //To operator + za�atwia sam 
float x, y;   float z = x + y;  
 
Zanim jednak stanie si� mo�liwe post�powanie takie: 
 
class CString x, y, z;     z = x + y;  
 
class Nasza_Klasa obiekt1, obiekt2, obiekt3;    
obiekt3 = obiekt1 + obiekt2;  
 
itp., itd. ... 
 
musimy "uzupe�ni�" C++ i "wyja�ni�" operatorom, co w�a�ciwie ma  
w praktyce oznacza� operacja   obiekt1 = obiekt2 + obiekt3; .  
Jest wyczuwalne intuicyjnie, �e dzia�anie operator�w w stosunku  
do r�nych obiekt�w mo�e by� r�ne. Dla przyk�adu - wiesz  
zapewne, �e inaczej wygl�da algorytm mno�enia liczb zespolonych, 
 
a inaczej liczb ca�kowitych rzeczywistych. Dlatego te� wykonanie 
 
operacji mno�enia wymaga od operatora * podj�cia r�nych  
dzia�a�:  
 
class Liczba_zespolona x, y, z;         z = x * y;  
 
int x, y, z;                            z = x * y;  
 
Czasem mo�e si� zdarzy�, �e dla dwu r�nych klas dzia�anie  
jakiego� operatora jest identyczne, cz�ciej jednak (i tak  
nale�y si� spodziewa�) dzia�anie operatora dla ka�dej klasy  
b�dzie odr�bne i unikalne.  
 
P�jd�my w tym rozumowaniu o krok dalej. Skoro rozszerzenie  
obszaru zastosowa� jakiego� operatora na obiekty nowej  
(nieznanej wcze�niej klasy) wymaga zdefiniowania nowego  
algorytmu dzia�ania operatora, C++ b�dzie potrzebowa� do tego  
celu specjalnych �rodk�w, kt�re powinny by� �atwo rozpoznawalne. 
 
Do opisu algorytm�w s�u�� generalnie w C++ funkcje i tu Autorzy  
nie wprowadzili wyj�tku. Zastrzegli jednak dla tych specjalnych  
funkcji specjaln� nazw�:              operator ...();  
 
I tak funkcja precyzuj�ca nowy algorytm dodawania (nowy spos�b  
dzia�ania operatora + ) b�dzie si� nazywa�:  
 
operator+();  
 
a np. funkcja okre�laj�ca nowy algorytm mno�enia (nowy spos�b  
dzia�ania operatora * ) b�dzie si� nazywa�:  
 
operator*();  
 
Spr�bujmy zastosowa� tak� filozofi� w praktyce programowania.  
 
[!!!] NIESTETY NIE WSZYSTKIE OPERATORY MO�NA ROZBUDOWA�. 
________________________________________________________________ 
S� w C++ operatory, kt�rych nie mo�emy podda� overloadingowi. S� 
 
to:  
 
.   ::   .*   ?:  
 
.   operator kropki umo�liwia dost�p do p�l struktur i obiekt�w; 
 
::  operator "widoczno�ci-przes�aniania" (ang. scope);  
.*  wskazanie cz�onka klasy (ang. pointer-to-member);  
?:  operator warunkowy.  
________________________________________________________________ 
 
Wszystkie pozosta�e operatory mo�emy podda� overloadingowi i  
przypisywa� im potrzebne nam dzia�anie. 
 
OVERLOADING OPERATORA [+] (DWUARGUMENTOWEGO). 
 
Zaczniemy od operatora + nale��cego do grupy "dwuargumentowych  
operator�w arytmetycznych" (ang. binary arithmetic operator).  
Zwracamy tu ju� na pocz�tku rozwa�a� uwag� na przynale�no��  
operatora do okre�lonej grupy, poniewa� overloading r�nych  
opertor�w nale��cych do tej samej grupy przebiega podobnie.  
Poniewa� znak + mo�e by� tak�e operatorem jednoargumentowym  
(ang. unary plus, o czym za chwil�), podkre�lamy, �e tym razem  
chodzi o plus jako operator dodawania. Overloading operatora  
przeprowadzimy w stosunku do obiekt�w prostej, znanej Ci ju� z  
poprzednich przyk�ad�w klasy Data, kt�r� (w celu upodobnienia  
si� do maniery stosowanej w Windows i bibliotekach klas)  
nazwiemy tym razem CData. "Nam�wimy" operator + do  
przeprowadzenia operacji na obiektach (dok�adniej na polach  
obiekt�w):  
 
CData nowadata = staradata + 7;       // W tydzien pozniej  
 
Operator + musi oczywi�cie "wiedzie�", na kt�rym polu obiekty  
klasy CData przechowuj� liczb� dni i jak zwi�zane s� (logicznie) 
 
pola obiektu dz, mc, rok. Jest rzecz� zrozumia��, �e samo  
dodanie dni do pola dz mo�e nie wystarczy�, poniewa� data  
37.11.93 jest niedopuszczalna.  
 
Je�li staradata jest obiektem klasy CData z zawartymi wewn�trz  
danymi, to w wyniku dzia�ania "nowego" operatora + powinien  
powsta� obiekt nowadata klasy CData, kt�rego pola zostan� w  
sensowny spos�b powi�kszone o dodan� liczb� dni. Rozwa�  
dzia�anie programu (najlepiej skompiluj i uruchom).  
 
[P120.CPP]  
 
/*  Overloading operatora dwuargumentowego +     */  
 
# include <iostream.h>  
 
class CData  
{  
  int dz, mc, rok;  
public:  
  CData() {}         //Konstruktor domyslny (pusty) 
  CData(int d, int m, int y) { mc = m; dz = d; rok = y; }  
  void Pokazuj() { cout << dz << '.' << mc << '.' << rok; }  
  CData operator+(int);       //TU! overloading operatora +  
};  
  
static int TAB[] = {31,28,31,30,31,30,31,31,30,31,30,31};  
 
/* Definicja funkcji operatorowej: ------------------------ */ 
 
CData CData::operator+(int n)  
{  
  CData kopia_obiektu = *this;  
  n += kopia_obiektu.dz;  
  while (n > TAB[kopia_obiektu.mc-1]) 
    {  
      n -= TAB[kopia_obiektu.mc-1];  
      if (++kopia_obiektu.mc == 13) 
         { kopia_obiektu.mc = 1; kopia_obiektu.rok++; }  
    }  
  kopia_obiektu.dz = n;  
  return (kopia_obiektu);  
}  
  
main()  
{  
  CData staradata(31, 1, 94);    //Kostruktor z argumentami 
  CData nowadata;                //Pusty konstruktor 
  cout << "\n Stara data: ";  
  staradata.Pokazuj();  
  cout << "\n Podaj ile minelo dni --> ";  
  int n;  
  cin >> n; 
  nowadata = staradata + n; 
  cout << "\n Jest zatem -->  "; 
  nowadata.Pokazuj();  
  return 0; 
}  
  
Do tej pory do danych prywatnych obiektu mogli�my si�gn��  
wy��cznie przy pomocy zdefiniowanej wewn�trz klasy  
funkcji-metody. Metod� umo�liwiaj�c� nam dost�p do prywatnych  
danych obiektu jest tu zadeklarowana wewn�trz klasy (a wi�c  
maj�ca "status prawny" metody) funkcja operatorowa. Przyjrzyjmy  
si� tej funkcji dok�adniej:  
 
CData CData::operator+(int n)  
{  
  CData kopia_obiektu = *this; 
 ...  
  return (kopia_obiektu);  
} 
 
Funkcja   
* zosta�a zdefiniowana dla obiekt�w klasy CData (z innymi  
post�powa� nie potrafi);  
Je�li operator + zostanie umieszczony pomi�dzy obiektem klasy  
CData, a liczb� typu int:  
                             .... staradata + n;  
* funkcja pobiera liczb� n jako argument (jawnie);  
* funkcja pobiera obiekt klasy CData jako sw�j drugi argument  
(niejawnie, dzi�ki pointerowi this); 
* funkcja zwr�ci obiekt klasy CData (ze zmodyfikowanym polem);  
 
Nowy obiekt zwr�cony przez funkcj� zostanie przypisany  
 
nowadata = ... ;      // <-- return(kopia_obiektu);  
 
W prawym polu operatora (operator jest dwuargumentowy, ma wi�c  
swoje lewe i prawe pole) mo�e pojawi� tak�e sta�a. Operacja:  
 
nowadata = staradata + 14;  
 
zostanie wykonana poprawnie.  
 
Ale to nie wszystko. Je�li wyst�pi uk�ad odwrotny - np.:  
 
nowadata = 14 + staradata;  
 
nasz operator "zg�upieje". Doszed�szy do operatora + C++ "nie  
b�dzie jeszcze wiedzia�" (analizuje wyra�enia arytmetyczne od  
lewej do prawej), KT�RY obiekt wyst�pi za chwil�. Jedno jest  
pewne, nie zawsze musi by� to "w�asny" obiekt funkcji, do  
kt�rego mamy pointer this. Aby uzyska� jednoznaczno�� sytuacji,  
funkcja operatorowa powinna tu w jawny spos�b pobiera� przed  
zadzia�aniem dwa argumenty:  
 
CData operator+(int n, CData obiekt);  
 
aby dzia�anie:  
 
CData obiekt_wynik;     obiekt_wynik = n + obiekt;  
 
sta�o si� wykonalne. Pojawia si� tu wszak�e pewien problem.  
Wska�nik this wskazuje w�asny obiekt funkcji-metody, a tym razem 
 
funkcja potrzebuje dost�pu nie do pola w�asnego obiektu, lecz do 
 
pola "obcego" obiektu przekazanego jej jako argument. Ale w C++  
mo�emy:  
 
* zdefiniowa� dwie (i wi�cej) funkcji o tej samej nazwie (ka�da  
na inn� ewentualno��);  
* mo�emy nada� funkcji status friend (wtedy nie b�d�c metod� te� 
 
uzyska dost�p do danych obiektu).  
 
Definicja naszej klasy CData zawieraj�ca deklaracje dwu funkcji  
operatorowych operator+() r�ni�cych si� zastosowaniem i (po  
czym rozpozna je C++) liczb� argument�w, b�dzie wygl�da� tak:  
 
class CData  
{  
  int dz, mc, rok;  
public:  
  CData() {}  
  CData(int d, int m, int y) { mc = m; dz = d; rok = y; }  
  void Pokazuj() { cout << dz <&lt...
Zgłoś jeśli naruszono regulamin