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 <<...
ZAZZY