Lab 3 - lab3_-_programowanie_obiektowe_c++
Transkrypt
Lab 3 - lab3_-_programowanie_obiektowe_c++
Informatyka II Laboratorium 3 : Programowania obiektowe C++ dziedziczenie Materiały: • • • • Książka: Symfonia C++, Jerzy Grębosz. Wykład: www.materialy.prz-rzeszow.pl, Informatyka II, dr Wojciech Rząsa. Zasoby WWW: http://pl.wikibooks.org/wiki/C++ , http://www.cplusplus.com. Wujek google. Zrealizuj poniższe zadania → jeśli masz jakiś problem to zapytaj prowadzącego. 1. Prosty przykład dziedziczenia klasy C++: Linia Kod programu 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <iostream> using namespace std; class KlasaBazowa { public: KlasaBazowa() { a = 0; } int a; }; class KlasaPochodna : public KlasaBazowa { public: int b; }; int main() { KlasaPochodna kp; kp.a = 5; kp.b = 4; Komentarz • • • zdefiniowanie klasy bazowej: ◦ konstruktor bezargumentowy ◦ jedno pole publiczne typu int • zdefiniowanie klasy KlasaPochodna, dziedziczącej z KlasaBazowa: ◦ typ dziedziczenia → public (są jeszcze private, protected), ◦ klasa z bazowa z której dziedziczy się metody i pola ◦ nie zapominaj o dwukropku!!! ◦ klasa pochodna ma jedno pole typu int z etykietą public cout << "Wartosc pola a: " << kp.a << endl; endl; } cout << "Wartosc pola a: " << kp.b << system("pause"); return 0; Dziedziczenie daje możliwość wykorzystania nowych klas w oparciu o stare klasy . Nowa klasa (pochodna) powiększa możliwości innej (wcześniejszej) klasy (bazowej). • utworzenie obiektu klasy pochodnej: ◦ obiekt kp ma pole b zdefiniowane w klasie ◦ również odziedziczył po klasie bazowej pole a!!!! 2. Etykiety dziedziczenia, etykiety klasy bazowej, a dostępność pól i metod klasy bazowej w klasie pochodnej: Typy dziedziczenia: ➢ public - oznacza, że dziedziczone metody i pola mają taką widoczność jak w klasie bazowej: public → public protected → protected private → brak dostępu w klasie pochodnej protected- oznacza, że pole/metody publiczne zmieniają się w chronione: public → protected protected → protected private → brak dostępu w klasie pochodnej private- oznacza, że wszystkie elementy klasy bazowej zmieniają się w prywatne dla klasy pochodnej: public → private protected → private private → brak dostępu w klasie pochodnej brak operatora - oznacza, że niejawnie (domyślnie) zostanie wybrany typ dziedziczenia private. Przykład: ➢ Linia Kod programu 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Komentarz #include <iostream> using namespace std; • class KlasaBazowa { public: KlasaBazowa() { a; } int a; }; class KlasaPochodna : public KlasaBazowa { public: int b; KlasaPochodna() { b = 0; } void Drukuj() { cout << "Pole klasy bazowej a: " << a << endl; cout << "Polde klasy pochodnej b: " << b << endl; } • }; int main() zdefiniowanie klasy bazowej: ◦ konstruktor bezargumentowy ◦ jedno pole publiczne zdefiniowanie klasy pochodnej: ◦ dziedziczy z klasy KlasaBazowa dziedziczenie public ◦ jedno pole public (lin. 16) ◦ utworzenie metody Drukuj(), która wypisuje wartość pól klasy bazowej i pochodnej ◦ pole klasy bazowej a: - etykieta public w klasie bazowej - dziedziczenia public - w związku z tym to pole w klasie pochodnej jest dostępne z etykietą public (na zewnątrz i wewnątrz klasy) ◦ • • utworzenie obiektu klasy pochodnej (linia 30) użycie metody drukuj (lin. 33) 1.Zamień linijkę 11: 29 30 31 32 33 34 35 36 37 { KlasaPochodna kp; kp.a = 5; kp.b = 4; kp.Drukuj(); system("pause"); return 0; } int a; na protected: int a; Spróbuj zbudować program: Pole z etykietą protected w klasie bazowej jest dostępne w klasie pochodnej z etykietę private (tylko wewnątrz klasy) → pojawi się błąd w trakcie budowania programu odnoszący się do instrukcji: kp.a = 5; 2. Zamień etykietę protected na private dla pola a i spróbuj zbudować program: Pole z etykietą private klasy bazowej nie jest w ogóle dostępne w klasie pochodnej ani na zewnątrz ani wewnątrz klasy. Pojawią się dwa błędy odnoszące się do linii: kp.a = 5; oraz cout << "Pole klasy bazowej a: " << a << endl; Tu wychodzi różnica dla etykiet pól/metod protected i private: • gdy nie ma dziedziczenia, to mają takie same działanie czyli dostęp pól/metod wewnątrz klasy • gdy jest dziedziczenie, to pola z etykietą private nie podlegają dziedziczeniu – nie są dostępne w klasie pochodnej, natomiast protected podlegają i są dostępne w klasie pochodnej tylko wewnątrz klasy 3. Dziedziczenie, a konstruktory: Linia Kod programu 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <iostream> using namespace std; class KlasaBazowa { public: KlasaBazowa(int _a) { a = _a; } protected: int a; }; class KlasaPochodna : public KlasaBazowa { public: KlasaPochodna(int _a, int _b) : KlasaBazowa(_a) { b = _b; } void Drukuj() { cout << "Pole klasy bazowej a: " << a << endl; cout << "Pole klasy pochodnej b: " << b << endl; } private: int b; }; int main() { KlasaPochodna kp(5,4); kp.Drukuj(); system("pause"); return 0; } Komentarz • zdefiniowanie klasy bazowej: ◦ konstruktor z parametrem, ustawiający pole a ◦ jedno pole protected • utworzenie klasy pochodnej: ◦ dziedziczenie public ◦ konstruktor dwuparametrowy - jeden parametr do ustawiania pola klasy pochodnej - drugi do ustawiania klasy bazowej - w celu ustawienia pola a, wywoływany jest konstruktor klasy bazowej (dwukropek i wywołanie bezpośrednie konstruktora klasy bazowej z parametrem) • jeśli klasa bazowa nie posiada konstruktora bez parametru, to klasa pochodna musi wywołać konstruktor klasy bazowej!!!!!!!!!!! wciąż możliwe jest przeciążanie konstruktorów dla klasy bazowej • 4. Zadanie do zrealizowania: a) Dopisz metodę do klasy Trojkat z poprzednich zajęć: UstawPole – prywatna metoda ustawiające pole (pole trójkąta). Napisz klasę TrojkatR (klasa pochodna, trójkąt równoboczny), która dziedziczy w sposób public z klasy Trojkat (klasa bazowa). Klasa posiada następujące metody: • Konstruktor- jednoargumentowy, przyjmuje jeden argument – bok trójkąta równobocznego, konstruktor musi wywołać konstruktor klasy bazowej, • ObliczPole – publiczna metoda obliczająca i ustawiająca pole (pola klasy bazowej) za pomocą metody UstawPole oraz zwracająca wartość pola trójkąta, pole trójkąta należy obliczyć ze wzoru: pole = a*a*sqrt(3)/4, długość boku należy pobrać za pomocą odpowiedniej metody. b) Napisać funkcję main w której należy: - utworzyć obiekt klasy Trojkat, - obliczyć i wydrukować wartość pola trójkąta, - utworzyć obiekt klasy TrojkatR, - obliczyć i wydrukować wartość pola trójkąta równobocznego. c) Rozszerzyć działanie klas Trojkat oraz TrojkatR, tak aby możliwe było obliczanie obwodu analogiczne do obliczania pola trójkąta. Przykładowe rozwiązanie dla 4 a) i b): ➢ Linia 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Kod programu #include <iostream> #include <math.h> using namespace std; class Trojkat { private: float x, y, z; float obw2; float pole; public: Trojkat(); Trojkat(Trojkat& trojkat); Trojkat(float _x, float _y, float _z) { if(SprawdzXYZ(_x, _y, _z)) { x = _x; y = _y; z = _z; } else { x = y = z = 0; } } static bool SprawdzXYZ(float _x, float _y, float _z); void UstawXYZ(float _x, float _y, float _z); Komentarz 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 78 79 80 81 82 83 84 85 86 87 private: void ObliczObw2(); public: float ObliczPole(); float ZwrocX(); // dokończyć samemu ZwrocY, ZwrocZ, ZwrocPole, ZwrocObw2 void UstawPole(float _pole) { pole = _pole; } }; class TrojkatR : public Trojkat { public: TrojkatR(float a) : Trojkat(a, a, a) { } float ObliczPole() { float a = ZwrocX(); float p = a*a* sqrt(3.0)/4; UstawPole(p); return p; } }; int main() { Trojkat t1(3,2,3); cout << "Pola trojkata wynosi: " << t1.ObliczPole() << endl; TrojkatR t2(3); cout << "Pole trojkata równobocznego wynosi: " << t2.ObliczPole() << endl; system("pause"); } Trojkat::Trojkat() { x = y = z = obw2 = pole = 0; } Trojkat::Trojkat(Trojkat& t) { x = t.x; y = t.y; z = t.z; obw2 = t.obw2; pole = t.pole; } bool Trojkat::SprawdzXYZ(float _x, float _y, float _z) { if(_x > 0 && _y > 0 && _z > 0) { if((_x + _y > _z) && (_y + _z > _x) && (_x + _z > _y)) { return true; } } return false; } void Trojkat::UstawXYZ(float _x, float _y, 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 float _z) { if(SprawdzXYZ(_x, _y, _z)) { x = _x; y = _y; z = _z; } } void Trojkat::ObliczObw2() { obw2 = (x + y + z) / 2; } float Trojkat::ObliczPole() { ObliczObw2(); pole = sqrt(obw2*(obw2 - x) * (obw2 y) * (obw2 - z)); return pole; } float Trojkat::ZwrocX() { return x; }