Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Programowanie obiektowe PO PO - LAB 4 Wojciech Pieprzyca.

Коpie: 1
Programowanie obiektowe PO PO - LAB 3 Wojciech Pieprzyca.

Podobne prezentacje


Prezentacja na temat: "Programowanie obiektowe PO PO - LAB 4 Wojciech Pieprzyca."— Zapis prezentacji:

1 Programowanie obiektowe PO PO - LAB 4 Wojciech Pieprzyca

2 Dla wbudowanych typów danych takich jak integer, double, float, itp. określone są operatory +,-,*,:, które wykonują podstawowe operacje arytmetyczne na liczbach tych typów. Okazuje się, że również dla typów (klas) definiowanych przez użytkownika możliwe jest określenie tych i innych operatorów. Wymaga to oczywiście dokładnego określenia tego jakie operacje mają być zrealizowane w ramach wywołania operatora. Mechanizm ten nazywany jest przeładowywaniem operatorów i wymaga zdefiniowania funkcji operatorowych. Typowa funkcja operatorowa ma postać: typ_zwracanego_wyniku operator rodzaj (lista_argumentów) np. zespolona operator+(zespolona a, zespolona b) Jak łatwo można się domyślić operator ten będzie realizował dodawanie dwóch liczb zespolonych. Operatory przeładowane (I) PO

3 Przykład: Mamy daną klasę liczb zespolonych (podobnie jak na zajęciach 1) class zespolona { private: int r,u; public: zespolona(int r, int u); zespolona(); void pokaz(); int pobierzR(); int pobierzU(); }; zespolona::zespolona(int _r, int _u) { r = _r; u = _u; } zespolona::zespolona()//konstruktor bezargumentowy { } Operatory przeładowane (II) PO

4 void zespolona::pokaz() { cout << r << + << u << i << endl; } int zespolona::pobierzR() { return r; } int zespolona::pobierzU() { return u; } Operatory przeładowane (III) PO

5 Dodatkowo określimy funkcję operatorową odpowiedzialną za dodawanie dwóch liczb zespolonych. Zauważmy, ze nie jest to funkcja składowa, ale zwykła funkcja globalna. zespolona operator+(zespolona a, zespolona b) { int r,u; r = a.pobierzR()+b.pobierzR(); u = a. pobierzU()+b.pobierzU(); zespolona wynik(r,u); return wynik; } Operatory przeładowane (IV) PO

6 Pozostaje nam określić operacje wykonywane w funkcji main: void main() { //pierwsza liczba zespolona zespolona a(10,5); //druga liczba zespolona zespolona b(2,3); zespolona suma;//tutaj uzyty zostanie konstruktor bezargumentowy //suma liczb zespolonych obliczana za pomocą operatora + //tutaj zadziala nasz operator zgodnie ze zdefiniowana funkcja operatorowa suma = a+b; //wyswietlenie wartosci liczb i sumy a.pokaz(); b.pokaz(); suma.pokaz(); } Operatory przeładowane (V) PO

7 Kilka zasad dotyczących operatorów: Przeładowywać można tylko i wyłącznie operatory wbudowane tzn. takie które już istnieją w języku C++, nie można wymyślać swoich operatorów, Lista operatorów, które można przeładować jest mimo to dosyć ogromna: + - * / % ^ & | ~ ! = += -= *= /= %= ^= &= |= > >>= <<= == != = && || ++ --, ->* -> new delete () [] Nie można zmieniać priorytetów operatorów tzn. że np. operator * zawsze będzie miał większy priorytet niż +, Nie można też zmienić liczby argumentów, na których działa operator, czyli operator * będzie nadal dwuargumentowy, a operator ++ jednoargumentowy. Przynajmniej jeden z argumentów musi być typu zdefiniowanego przez użytkownika tzn. że nie można po raz drugi zdefiniować jak zachowują się operatory dla typów wbudowanych. Operatory przeładowane (VI) PO

8 W poprzednim przykładzie funkcja operatorowa została zdefiniowana w zakresie globalnym i nie była składową żadnej klasy ani też z nią nie posiadała żadnych innych relacji. Teraz zobaczymy, że funkcja ta może być także metodą składową klasy, wymaga to jednak wprowadzenia pewnych zmian. A zatem jak wygląda funkcja operatorowa będącą składową klasy ? Oto rozwiązanie: zespolona zespolona::operator+(zespolona b) { int rr,uu; rr = r+b.r; uu = u+b.u; zespolona wynik(rr,uu); return wynik; } Różnice na pierwszy rzut oka są mało widoczne, ale po bliższym przyjrzeniu się definicji funkcji widać, że… Funkcje operatorowe jako składowe (I) PO

9 … widać, że funkcja przyjmuje tylko jeden argument, liczbę zespoloną oznaczoną jako b. Powstaje pytanie skąd w takim razie bierzemy wartości dla liczby zespolonej a. Otóż, trzeba zdać sobie sprawę, że każda funkcja (metoda) składowa jest uruchamiana na rzecz jakiegoś obiektu (w tym przypadku np. obiektu typu zespolona reprezentującego liczbę zespoloną a). Nie potrzebujemy już zatem drugiego argumentu (obiektu) funkcji, gdyż dostęp do składowych tego obiektu mamy automatycznie, gdyż ta metoda wywoływana jest właśnie przez ten obiekt. Nie musimy już zatem wywoływać a.pobierzU(), ale samo pobierzU(), podobnie jest z metodą pobierzR(). Ogólna zasada jest taka: Funkcja operatorowa zdefiniowana jako metoda składowa klasy przyjmuje zawsze o jeden argument mniej niż ta sama funkcja operatorowa zdefiniowana jako funkcja globalna. PS. Aby to zadziałało konieczne jest dopisanie nagłówka funkcji operatorowej do definicji klasy, w końcu to będzie nowa metoda klasy!, proszę o tym nie zapomnieć. Funkcje operatorowe jako składowe (II) PO

10 Nie odpowiedzieliśmy sobie jeszcze na pytanie czy zajdą jakieś zmiany w funkcji main ? To zadziwiające, ale nie będzie żadnych zmian. Wywołanie funkcji operatorowej na rzecz obiektu a wykona się niejako za kurtyną, bez naszej wiedzy. Nadal sumowanie liczb zespolonych odbędzie się za pomocą instrukcji: suma = a+b; Wszystko stanie się jasne, gdy uświadomimy sobie, że faktyczne wywołanie operacji a+b ma postać: a.operator+(b) czyli, że to obiekt a wywołuje funkcję operatorową i przekazuje jej jako argument obiekt b. W uproszczeniu możemy napisać a+b, ale realizacja jest taka sama jak powyżej. Funkcje operatorowe jako składowe (III) PO

11 W zasadzie wszystko jest już jasne. Możemy tworzyć funkcje operatorowe w dwojaki sposób: 1)Jako funkcje globalne, 2)Jako składowe klas. Znamy już różnicę i konieczność innego sposobu definiowania funkcji w obu przypadkach. Ale jest jeszcze coś… Zauważmy, że w przypadku budowy funkcji operatorowej jako globalnej, dostęp do składowych klas jest bardzo ograniczony. Zgodnie z zasadą enkapsulacji, możemy odwołać się tylko do składowych publicznych lub też napisać odpowiednie metody akcesorowe i odwoływać się poprzez ich użycie. Pisanie metod akcesorowych dla wszystkich składowych może być jednak uciążliwe. Dlatego czasami lepiej po prostu przyznać funkcjom operatorowym odpowiednie uprawnienia dostępowe do składowych prywatnych klasy. Możemy to zrobić, gdyż znamy już mechanizm zaprzyjaźniania się klasy z jakąś funkcją. W naszym przypadku klasa zespolona zadeklaruje przyjaźń z funkcję operatorową. Funkcje operatorowe a przyjaźń (I) PO

12 Zacznijmy zatem od początku i deklaracji klasy. Pozbędziemy się z niej metod akcesorowych i zadeklarujmy przyjaźń z funkcją operatorową. class zespolona { friend zespolona operator+(zespolona a, zespolona b); private: int r,u; public: zespolona(int r, int u); zespolona(); void pokaz(); }; zespolona::zespolona(int _r, int _u) { r = _r; u = _u; } zespolona::zespolona()//konstruktor bezargumentowy { } Funkcje operatorowe a przyjaźń (II) PO

13 void zespolona::pokaz() { cout << r << + << u << i << endl; } zespolona operator+(zespolona a, zespolona b) { int r,u; //juz nie musimy korzystac z metod akcesorowych r = a.r+b.r; u = a.u+b.u; zespolona wynik(r,u); return wynik; } Funkcja main pozostaje bez zmian. Funkcje operatorowe a przyjaźń (III) PO

14 1.Rozwiń klasę zespolona o dodatkowe operatory przeładowane – i * działające zgodnie z poniższymi wzorami: z1 – z2 = (a-c) + (b-d)i z1 * z2 = (ac – bd) + (ad + bc)i Stwórz 3 wersje: 1) funkcja operatorowa globalna - z użyciem składowych prywatnych i metod akcesorowych, 2) funkcja operatorowa jako metoda klasy - z użyciem składowych prywatnych, 3) funkcja operatorowa globalna - z użyciem składowych prywatnych i przyjaźnią z funkcją operatorową, 2.Zdefiniuj klasę tekst, przechowującą tekst o długości do 100 znaków i zawierającą przeładowane operatory + i -. Operator + ma dołączać podany ciąg znaków do istniejącego tekstu, a operator – ma usuwać z tekstu wszystkie wystąpienia podanego znaku. Standardowo należy zdefiniować konstruktor i metodę wyświetlającą aktualną zawartość łańcucha tekstowego. Ćwiczenia PO


Pobierz ppt "Programowanie obiektowe PO PO - LAB 4 Wojciech Pieprzyca."

Podobne prezentacje


Reklamy Google