Laboratorium 4 - Kajetan Kurus
Transkrypt
Laboratorium 4 - Kajetan Kurus
Laboratorium 4 - dziedziczenie, klasy abstrakcyjne, polimorfizm mgr inż. Kajetan Kurus 25 marca 2014 1 Podstawy teoretyczne 1. Dziedziczenie (a) dziedziczenie pól i metod (b) przesłanianie funkcji (c) widoczność elementów: public, private, protected 2. Polimorfizm 3. Funkcje wirtualne 4. Klasy abstrakcyjne 2 Zadanie do rozwiązania na zajęciach 2.1 Treść zadania 1. Należy stworzyć klasę pojazd, będącą ”‘ogólną klasą”’ reprezentującą wszystkie możliwe pojazdy kołowe. Klasa pojazd ma zawierać konstruktor parametryczny i bezparametryczny, pole kola oraz metodę dodajKola z jednym parametrem. Następnie należy stworzyć dwie klasy (osobowy i quad ) dziedziczące po klasie pojazd. Do klasy osobowy należy dodać pole osoby oraz metodę dodajOsoby . Natomiast w klasę quad należy przesłonić metodę dodajKola aby dodawała tylko wartość 4 ignorując argument wejściowy. 2. Sworzyc klasę abstrakcyjną jednostkaPlywajaca , która zawiera metody wirtualne plyn, cumuj oraz predkosc. Następnie należy stworzyć dwie klasy dziedziczące po jednostkaPlywajaca: jacht oraz tankowiec. Należy sprawdzić czy możliwe jest stworzenie obiektu klasy jednostkaPlywajaca oraz jacht, gdy nie wszystkie metody z jednostkaPlywajaca są zaimplementowane. 1 2.2 Rozwiązanie zadania 1 Dziedziczenie po danej klasie umożliwia przejmowanie jej pól i metod widocznych jako public i protected. Dzięki takiemu rozwiązaniu można tworzyć co raz bardziej wyspecjalizowane klasy bez potrzeby kopiowania/implementowania na nowo istniejących metod. W przypadku, gdy w najwyższej klasie dokonamy modyfikacji lub dodamy nową funkcjonalność, nie będzie konieczności zmiany reszty klas. Aby dziedziczyć po klasie należy podczas tworzenia klasy potomnej zawrzeć odniesienie do klasy bazowej. 1 2 3 class ... }; klasaPotomna : public klasaBazowa { Dodanie parametru widoczności informuje kompilator jak mają być widoczne elementy klasy bazowej. public: public → public protected → protected protected: public → protected protected → protected private: lub brak operatora public → private protected → private Należy pamiętać, że elementów private: z klasy bazowej nie można dziedziczyć. Czasami istnieje potrzeba zmiany dziedziczonej metody aby spełniała kryteria klasy potomnej. Można tego dokonać przesłaniając konkretną funkcję. Polega to na re-deklaracji metody wewnątrz nowej klasy i ponowne jej zdefiniowanie. Przykładem przesłaniania funkcji jest klasa quad i jej metoda dodajKola. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #i n c l u d e <i o s t r e a m > #i n c l u d e <s t r i n g > u s i n g namespace s t d ; c l a s s pojazd { // K l a s a bazowa public : pojazd () ; pojazd ( int k ) ; void dodajKola ( i n t k ) ; protected : i n t kola ; private : string info ; }; pojazd : : pojazd () { kola = 0 ; } pojazd : : pojazd ( int k ){ kola = k ; } 2 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 void pojazd : : dodajKola ( i n t k ) { kola = k ; c o u t << ” dodano k o l : ” <<k<<e n d l ; } c l a s s osobowy : public pojazd { public : osobowy ( int k , int o ) ; void dodajOsobe ( i n t o ) ; private : int osoby ; }; osobowy : : osobowy ( int k , kola = k ; osoby = o ; } // K l a s a d z i e d z i c z a c a po k l a s i e p o j a z d int o){ void osobowy : : dodajOsobe ( i n t o ) { osoby = o ; c o u t << ” dodano o s o b : ” << o <<e n d l ; } c l a s s quad : public pojazd { public : quad ( i n t k ) ; void dodajKola ( i n t k ) ; bazowej pojazd }; // K l a s a d z i e d z i c z a c a po k l a s i e p o j a z d // P r z e s l a n i a n i e metody d o d a j K o l a z k l a s y ←- quad : : quad ( i n t k ) { kola = k ; } void quad : : dodajKola ( i n t k ) { kola = 4 ; c o u t<<” quad moze miec t y l k o 4 k o l a ”<<e n d l ; } void main ( ) { pojazd P ; osobowy O (4 ,4) ; quad Q (4) ; P. O. O. Q. dodajKola (8) ; dodajKola (4) ; dodajOsobe (2) ; dodajKola (5) ; s y s t e m ( ”PAUSE” ) ; } Po uruchomieniu programu widać, że dla obiektów klasy pojazd i osobowy metoda dodajKola wyświetla komunikat o dodaniu nowej ilości kół. Natomiast dla obiektu klasy quad wywołanie tej samej metody skutkuje wywołaniem jej własnej funkcji. 3 2.3 Rozwiązanie zadania 2 Klasa abstrakcyjna jest specyficzną formą klasy, która ma za zadanie wymuszać na klasach dziedziczących własne implementacje podanych metod. Klasa czysto abstrakcyjna zawiera w sobie tylko metody wirtualne dodatkowo zapisane wartością 0. c l a s s abstrakcyjna { v i r t u a l void metodaAbstrakcyjna () = 0; }; 1 2 3 Każda klasa dziedzicząca po klasie abstrakcyjnej ma obowiązek zaimplementować pewne metody, w innym przypadku obiekty tej klasy nie będą mogły być utworzone. 1 2 3 4 5 6 7 8 9 10 11 12 #i n c l u d e <i o s t r e a m > u s i n g namespace s t d ; class jednostkaPlywajaca { public : v i r t u a l void plyn ( ) = 0 ; v i r t u a l bool cumuj () = 0; v i r t u a l void predkosc ( i n t v ) = 0; }; // metoda w i r t u a l n a // metoda w i r t u a l n a // metoda w i r t u a l n a tankowiec : public jednostkaPlywajaca { // k l a s a abstrakcyjnej void plyn ( ) ; // i m p l e m e n t a c j a abstrakcyjnej bool cumuj () ; // i m p l e m e n t a c j a abstrakcyjnej void predkosc ( i n t v ) ; // i m p l e m e n t a c j a abstrakcyjnej int speed ; class 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 // d e k l a r a c j a k l a s y a b s t r a k c y j n e j }; void tankowiec : : plyn ( ) { c o u t<<” t a n k o w i e c p l y n i e ”<<e n d l ; } bool tankowiec : : cumuj () { c o u t<<” t a n k o w i e c cumuje ”<<e n d l ; return true ; } void tankowiec : : predkosc ( i n t v ) { speed = v ; } 4 d z i e d z i c z a c a po k l a s i e ←metody k l a s y ←metody k l a s y ←metody k l a s y ←- 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 c l a s s j a c h t : p u b l i c j e d n o s t k a P l y w a j a c a { // k l a s a d z i e d z i c z a c a po k l a s i e ←abstrakcyjnej void plyn ( ) ; // i m p l e m e n t a c j a metody k l a s y ←abstrakcyjnej int speed ; }; void jacht : : plyn ( ) { c o u t<<” j a c h t p l y n i e ”<<e n d l ; } void main ( ) { // jednostkaPlywajaca P; // K o m p i l a t o r n i e p o z w o l i s t w o r z y c o b i e k t u k l a s y ←abstrakcyjnej tankowiec T ; // jacht J ; // K o m p i l a t o r n i e p o z w o l i s t w o r z y c o b i e k t u j a c h t , ←poniwaz n i e z a i m p l e m e n t o w a l w s z y s t k i c h metod d z i e d z i c z o n y c h po ←jednostkaPlywajaca s y s t e m ( ”PAUSE” ) ; } Powyższy program został zakomentowany w dwóch miejscach w celu poprawnej kompilacji. Obiekt klasy jednostkaPlywajaca nie może zostać stworzony, ponieważ jest to klasa abstrakcyjna o czym informuje nas kompilator na obrazku poniżej. Dla klasy jacht nie zostały zaimplementowane wszystkie metody z klasy wirtualnej przez co jej obiekt również nie może zostać stworzony. 5 3 Zadania indywidualne Termin oddania 01-04-2014 3.1 Ocena 3.0 Zadanie z laboratorium Dopisać metodę jedz() i hamuj(), które zmodyfikują pole bool pojazdWRuchu dla klasy pojazd Sprawdzić działanie nowych metod dla obiektów klasy quad i osobowy Stworzyć klasę sedan dziedzicząca po klasie osobowy i przesłonić metodę dodajOsobe (dowolne działanie) 3.2 Ocena 4.0 Zadanie z laboratorium Zadanie na 3.0 Dopisać brakujące metody tak, aby można było stworzyć obiekt klasy jacht. Stworzyć w klasie tankowiec metodę wirtualną zrzutPaliwa, która nie zrobi z niej klasy abstrakcyjnej (należy zaimplementować metodę w klasie) Stworzyć klasę superTankowiec dziedziczącą po klasie tankowiec i zaimplementować zrzutPaliwa . Utworzyć w main obiekty każdej z klas i przetestować metody. Przypisać do nowego obiektu tankowiec, wskaźnik do obiektu superTankowiec a następnie wywołać metodę zrzutPaliwa (kod poniżej). W komentarzu opisać co się stało. 1 2 3 4 5 6 7 tankowiec T ; s u p e r t a n k o w i e c sT ; T . zrzut () ; sT . zrzut ( ) ; t a n k o w i e c * wT ; w T = &s T ; // z a m i s t &s t moze byc new s u p e r t a n k o w i e c ( ) ; wT−>z r z u t ( ) ; 3.3 Ocena 5.0 Zadanie z laboratorium Zadanie na 3.0 Zadanie na 4.0 6 Stworzyć klasę abstrakcyjną samolot zawierającą metody startuj(), ląduj(), tankuj() Stworzyć jedną klasę abstrakcyjną odrzutowiec dziedziczącą po samolot, dodającą kolejne metody zwiekszCiag() i zmniejszCiag() Stworzyć klasę smiglowy dziedziczącą po samolot zawierającą metodę wirtualną zakrecSmiglem Stworzyć klasę awionetka oraz herkules. Dla klasy herkules zaimplementować nową metodę zakrecSmiglem . Analogicznie do ostatniego punktu oceny na 4.0, do obiektu klasy smiglowy przypisać wskaźnik do awionetka i herkules. Wyniki zapisać w komentrzu Stworzyć klasę lightJet dziedziczący po klasie odrzutowiec. 7