Wykład 4 Wybrane zagadnienia programowania w C++ Przykład programu obiektowego Dziedziczenie polimorfizm i metody wirtualne Wzorce (szablony) funkcji Wzorce klas 2016-01-03 Bazy danych-1 W4 1
Dziedziczenie polimorfizm i metody wirtualne Dziedziczenie jest techniką, która pozwala na definiowanie nowej klasy przy wykorzystaniu klasy już istniejącej. Polimorfizm to najważniejsza cecha programowania obiektowego. Oznacza, że implementacja pewnych funkcji (metod) może przybierać wiele różnych form. Metody wirtualne słowo kluczowe virtual poprzedza te metody, które w klasach bazowych mają taką samą nazwę, ale inną niż w klasie bazowej implementację. Metody takie wywołane na rzecz obiektu klasy potomnej realizują swój algorytm specyficzny dla klasy potomnej. 2016-01-03 Bazy danych-1 W4 2
2016-01-03 Bazy danych-1 W4 3
2016-01-03 Bazy danych-1 W4 4
2016-01-03 Bazy danych-1 W4 5
2016-01-03 Bazy danych-1 W4 6
Uwagi i komentarze: 1. W klasie bazowej pola opatrzone modyfikatorem dostępu protected są dostępne z obiektów danej klasy i z obiektów klas potomnych. 2. Akcesory są niezbędne, aby można było odczytywać i modyfikować pola chronione 3. Klasa potomna "wyprowadzona" z klasy bazowej: nazwę klasy bazowej podaje się po znaku dwukropka 4. Pole z oznaczone jako chronione na wypadek, gdyby klasa PUNKT_3D była kiedyś klasą bazową dla kolejnych potomków. 5. Konstruktor klasy potomnej uwaga: nie ma dziedziczenia konstruktora domyślnego 6. Metody wyswietl i przesun w klasie potomnej mają takie same nazwy jak metody w klasie bazowej, spełniają taką samą rolę, ale ich implementacje różnią się ponieważ odnoszą się do obiektów różnych klas o różnych cechach, a więc obiektów, których zachowanie jest różne. 7. Niezbędne akcesory do pola chronionego 8. Definicja metody wyswietl klasy potomnej 9. Definicja metody przesun klasy potomnej 2016-01-03 Bazy danych-1 W4 7
10. Nie można np. zadeklarować obiektu D bez jawnego wywołania konstruktora w klasie potomnej, bowiem konstruktor domyślny z klasy bazowej nie podlega dziedziczeniu 11. A tutaj zadziała konstruktor domyślny obiektu klasy bazowej 12. Zmiana i odczyt wartości pól chronionych za pomocą akcesorów 13. Wywołanie metody wyswietl klasy potomnej 14. Wywołanie metody przesun klasy potomnej 15. Wywołanie metod wyswietl i przesun klasy bazowej 2016-01-03 Bazy danych-1 W4 8
2016-01-03 Bazy danych-1 W4 9
2016-01-03 Bazy danych-1 W4 10
2016-01-03 Bazy danych-1 W4 11
W przykładzie znajdują się deklaracje 3 klas: Figura, Kwadrat i Kolo. W klasie Figura została zadeklarowana metoda wirtualna float pole()(słowo kluczowe virtual). Każda z klas pochodnych od klasy Figura ma zaimplementowane swoje specyficzne metody obliczania pola powierzchni float pole(). Następnie (w funkcji main) znajdują się deklaracje obiektów każdej z klas i wskaźnika na obiekty klasy bazowej Figura. Wywołanie metod składowych dla każdego z obiektów powoduje wykonanie metody odpowiedniej dla klasy danego obiektu. Następnie wskaźnikowi wskjakasfigura zostaje przypisany adres obiektu jakasfigura i zostaje wywołana metoda float pole(). Wynikiem jest "-1" zgodnie z treścią metody float pole() w klasie Figura. Następnie przypisano wskaźnikowi adres obiektu klasy Kwadrat - możemy tak zrobić ponieważ klasa Kwadrat jest klasą pochodną od klasy Figura - jest to tzw. rzutowanie w górę. Wywołanie teraz metody float pole() dla wskaźnika nie spowoduje wykonania metody zgodnej z typem wskaźnika - który jest typu Figura* lecz zgodnie z aktualnie wskazywanym obiektem, a więc wykonana zostanie metoda float pole() z klasy Kwadrat (gdyż ostatnie przypisanie wskaźnikowi wartości przypisywało mu adres obiektu klasy Kwadrat). Analogiczna sytuacja ma miejsce, gdy przypiszemy wskaźnikowi adres obiektu klasy Kolo. 2016-01-03 Bazy danych-1 W4 12
Następnie zostaje wywołana funkcja void wyswietlpole(figura&) która przyjmuje jako parametr obiekt klasy Figura przez referencję. Tutaj również zostały wykonane odpowiednie metody dla obiektów klas pochodnych, a nie metoda zgodna z obiektem jaki zadeklarowano jako parametr funkcji czyli float Figura::pole(). Takie działanie jest spowodowane bo przyjęto obiekt klasy Figura przez referencję. Gdyby obiekty były przyjmowane przez wartość (parametr bez &) zostałaby wykonana trzykrotnie metoda float Figura::pole() i trzy krotnie wyświetlona wartość -1. Takie działanie spowodowało określenie metody w klasie bazowej jako wirtualnej. Gdyby zostało usunięto słowo kluczowe virtual w deklaracji metody w klasie bazowej, zostałyby wykonane metody zgodne z typem wskaźnika lub referencji, a więc za każdym razem wykonana metoda float pole() z klasy Figura. 2016-01-03 Bazy danych-1 W4 13
2016-01-03 Bazy danych-1 W4 14
2016-01-03 Bazy danych-1 W4 15
2016-01-03 Bazy danych-1 W4 16
2016-01-03 Bazy danych-1 W4 17
Uwagi i komentarze: 1. Metody wyswietl i przesun poprzedzone słowem virtual działają w różny sposób w zależności od klasy obiektu 2. Klasa potomna implementuje punkt w przestrzeni 3D 3. Klasa potomna dziedziczy z klasy bazowej składowe x oraz y i ma dodatkowo swoją specyficzną składową z; składowa z oznaczona jako chroniona na wypadek, gdyby klasa PUNKT_3D była kiedyś klasą bazową dla kolejnych potomków. 4. Metody wyswietl i przesun oznaczono jako wirtualne z powodu j.w. Metody wyswietl i przesun w klasie potomnej mają takie same nazwy jak metody w klasie bazowej, spełniają taką samą rolę, ale ich implementacje różnią się ponieważ odnoszą się do obiektów różnych klas o różnych cechach, a więc obiektów, których zachowanie jest różne. 5. Utworzono obiekty A, B i D klasy potomnej 6. Utworzono obiekt C klasy bazowej 7. Niezbędne akcesory aby udostępnić pola chronione 8. Wywołano metodę wyswietl na rzecz obiektów klasy potomnej 9. Wywołano metodę wyswietl na rzecz obiektu klasy bazowej 10. Przesuwam i wyświetlam obiekty klasy potomnej 11. Przesuwam i wyświetlam obiekt klasy bazowej 2016-01-03 Bazy danych-1 W4 18
Wzorce (szablony) funkcji Szablon jest mechanizmem, który służy do tworzenia "rodziny" podobnych funkcji/klas różniących się typem argumentów. Szablon funkcji ma postać ogólną: template <class typ> typ funkcja(typ arg1, typ arg2,, typ argn) { // ciało funkcji } gdzie: typ występujący po słowie kluczowym class jest "parametrem szablonu"; arg1,, argn argumenty "funkcji szablonowej" Parametr szablonu musi wystąpić jako typ argumentu funkcji definiowanej tym szablonem. 2016-01-03 Bazy danych-1 W4 19
2016-01-03 Bazy danych-1 W4 20
2016-01-03 Bazy danych-1 W4 21
Wzorce klas Podobną składnię i mechanizm działania posiadają wzorce (szablony) klas, które kompilator wykorzystuje do generowania określonych wyspecjalizowanych klas. Szablon klasy stanowi wówczas wzór, wg którego kompilator utworzy definicję w momencie pojawienia się deklaracji obiektu określonej szczególnej klasy. 2016-01-03 Bazy danych-1 W4 22
2016-01-03 Bazy danych-1 W4 23
2016-01-03 Bazy danych-1 W4 24
2016-01-03 Bazy danych-1 W4 25