Podstawy programowania w języku C++ Zadania - dziedziczenie i polimorfizm Mirosław Głowacki 1,2 1 Akademia Górniczo-Hutnicza im. Stanisława Staszica w Ktrakowie Wydział Inżynierii Metali i Informatyki Stosowanej Katedra Informatyki Stosowanej i Modelowania 2 Uniwersytet im. Jana Kochanowskiego w Kielcach Wydział Matematyczno-Przyrodnmiczy Instytut Fizyki Zakład Informatyki Maj 2017 Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 1 / 11
Spis treści 1 Zadania L7 2 Podpowiedzi do zadań L7 Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 2 / 11
Dziedziczenie i polimorfizm - L7/1-3 1 Zdefiniować klasę punkt zawierającą w zakresie publicznym: dwa pola przechowujące współrzędne punktu, konstruktor, metodę obliczającą odległość dwóch punktów. 2 Zdefiniować klasę figura zawierającą w zakresie publicznym: pole typu int przechowujące liczbę wierzchołków figury, dynamiczną tablicę przechowującą wierzchołki figury, konstruktor. 3 Zdefiniować klasę odcinek wywodzącą się z klasy figura zawierającą w zakresie publicznym: konstruktor, metodę obliczającą długość odcinka. Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 3 / 11
Dziedziczenie i polimorfizm - L7-4 4 Zdefiniować odpowiednie przeciążenia operatorów tak, aby całość kodu pozwoliła na wykonanie kodu programu: int main(){ punkt p[2] = { punkt(1., 2.), punkt(3., -3.) }; odcinek o(p); cout << " Odcinek o: " << o << " ma dlugosc= " << o.dlug() << endl; return 0; } oraz uzyskanie strumienia wyjściowego: Odcinek o: (1, 2) - (3, -3) ma dlugosc= 5.38516 Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 4 / 11
Dziedziczenie i polimorfizm - L7-5 5 Uzupełnić kod z poprzednich zadań, aby możliwe było wykonanie funkcji main() : double obwod(figura &f){return f.obwod();} int main(){ punkt p[] = { punkt(1., 2.), punkt(3., -3.), punkt(4., -3.), punkt(5., 3.) }; odcinek o(p); cout << " Odcinek o: " << o << " ma dlugosc= " << o.dlug() << endl; trojkat t(p); cout << "Obwod trojkata = " << obwod(t) << endl; czworokat c(p); cout << "Obwod trojkata = " << obwod(c) << endl; return 0; } Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 5 / 11
Spis treści 1 Zadania L7 2 Podpowiedzi do zadań L7 Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 6 / 11
Podpowiedzi do zadania L7/1-4 Definicja klasy punkt nie wymaga dodatkowych wyjaśnień. Klasa figura jest zaprojektowana tylko po to, aby inne klasy mogły z niej dziedziczyć - np. klasa odcinek. Dlatego ma zawierać pole typu int, w którym zapamiętamy liczbę wietzchołków. Same wierzchołki które są obiektami klasy punkt będzie zawierać tablica w o elementach typu punkt. Ponieważ rozmiar tej tablicy jest z góry nieznany - może to być 2 dla odcinka lub np. 100 dla stukąta - będzie to tablica dynamiczna, a klasa powinna zawierać m. in. pole-wskaźnik do tej tablicy: class figura{ public:... punkt *w;... }; Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 7 / 11
Podpowiedzi do zadania L7/1-4 Tablica powinna być zdefiniowana w konstruktorze, a zlikwidowana w destruktorze klasy figura. Uwolni to programistę od konieczności ręcznej likwidacji tablicy gdy przestanie być potrzebna. class figura{ public:... figura(int, punkt*); ~figura(){delete [] w;} } figura::figura(int n, punkt *p) : lwierzch(n){ w = new punkt[n]; for (int i = 0; i < lwierzch; i++) w[i] = p[i]; } Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 8 / 11
Podpowiedzi do zadania L7/1-4 Jak widzimy konstruktor klasy figura ma dwa jawne parametry: liczbę wierzcholków n i tablicę p obiektów typu punkt. Parametry takie przekaże mu konstruktor klasy odcinek (lub konstruktor innej klasy, która będzie dziedziczyć z klasy figura ) class odcinek : public figura{ public: odcinek(punkt *p) : figura(2, p){}... } }; Konstruktor odcinka otrzma zaś tablicę p z funkcji main() : odcinek o(p); Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 9 / 11
Podpowiedzi do zadania L7/1-4 Aby możliwa była instrukcja cout << o gdzie o jest obiektem klasy odcinek należy przeciążyć operator zrzucania do strumienia dla obiektów klasy odcinek. Powinien on używać przeciążonego wcześniej opratora dla klasy punkt postaci: ostream& operator<<(ostream& str, punkt p) { str << "(" << p.x << ", " << p.y << ")"; return str; } Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 10 / 11
Podpowiedzi do zadania L7/5 Rozwiązanie zadania wymaga polimorficznego zachowania przedstawionej w treści zadania funkcji obwod. Funkcja ta posługuje się metodą obwód pracującą w ciele funkcji na rzecz obiektu f - referencji typu figura. Funkcja obwód wywoływana jest w funkcji main() na rzecz obiektów dwóch różnych klas: trojkat i czworokat. trojkat t(p); cout << obwod(t); czworokat c(p); cout << obwod(c); Aby to było możliwe polimorfizm musi działać, czyli: Klasa figura musi posiadać wirtualną metodę virtual double obwod(){};, Klasy trojkat i czworakat muszą dziedziczyć z klasy figura oraz posiadać obliczające ich obwody metody double obwod(); o identycznym prototypie. Mirosław Głowacki (AGH, UJK) Podstawy programowania - dziedziczenie 2017 11 / 11