• Nie Znaleziono Wyników

Dariusz Wardowski

N/A
N/A
Protected

Academic year: 2021

Share "Dariusz Wardowski"

Copied!
12
0
0

Pełen tekst

(1)

Dariusz Wardowski

(2)

dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 2/12

Relacje między klasą macierzystą a potomną

Dyrektor anna(500,„Anna”, „Lis”, „Dyrektor”, 3000);

Anna.wypiszDane();

• Obiekt klasy potomnej może korzystać z metod klasy macierzystej.

• Wskaźnik do klasy macierzystej może wskazywać na obiekt klasy potomnej.

Pracownik* p1;

p1 = &anna;

p1->wypiszDane();

• Referencja do klasy macierzystej może odnosić się do obiektu klasy macierzystej.

Pracownik& p2;

p2 = anna;

p2.wypiszDane();

•Metody zdefiniowane w klasie potomnej mogę być wywołane jedynie przez referencję lub wskaźnika do obiektu klasy potomnej.

p1->setDodatekFunkcyjny(500); //błąd!!!

• Nie można przypisywać adresów i obiektów klasy macierzystej do wskaźników i referencji klasy potomnej.

Pracownik p3();

Dyrektor& d1 = p3; //błąd!!!

Dyrektor* d2 = &p3; //błąd!!!

(3)

Funkcje a referencje i wskaźniki do klasy macierzystej

void wypisz(Pracownik & p) {

cout << „Dane pracownika: ” << endl;

p.wypiszDane();

}

Funkcje, których parametrami są wskaźniki lub referencje do klasy macierzystej mogą być używane zarówno z obiektami klasy macierzystej jak i potomnej.

Powyższą funkcje możemy wywołać zarówno z argumentami typu Pracownik jak i Dyrektor:

Pracownik zenek;

Dyrektor wlodek;

wypisz(zenek);

wypisz(wlodek);

Analogicznie dla wskaźników:

void wypisz(Pracownik * p) {

cout << „Dane pracownika: ” << endl;

p->wypiszDane();

}

wypisz(&zenek);

wypisz(&wlodek);

(4)

dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 4/12

Inicjalizacja obiektu klasy macierzystej za pomocą obiektu klasy potomnej

Dyrektor dyr(300, „Jan”, „Kowalski”, „Dyrektor”, 3000);

Pracownik p(dyr);

Zgodność referencji typu klasy macierzystej z obiektami klasy potomnej daje również możliwość wykorzystywania obiektów klasy potomnej do tworzenia obiektów klasy macierzystej.

W powyższej sytuacji działa konstruktor kopiujący klasy macierzystej:

Pracownik(const Pracownik &);

(5)

Przypisanie obiektu klasy potomnej do obiektu klasy macierzystej

Dyrektor dyr(300, „Jan”, „Kowalski”, „Dyrektor”, 3000);

Pracownik p;

p = dyr;

Zgodność referencji typu klasy macierzystej z obiektami klasy potomnej daje również możliwość przypisywanie obiektów klasy potomnej do obiektów klasy macierzystej.

W powyższej sytuacji działa w sposób niejawny operator przypisania:

Pracownik & operator=(const Pracownik &) const;

Referenja do klasy macierzystej odwołuje się w tym przypadku do klasy potomnej, kopiowana jest jedynie część „macierzysta” obiektu dyr do obiektu p.

(6)

dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 6/12

Rodzaje dziedziczenia

C++ wyróżniamy trzy rodzaje dziedziczenia:

• publiczne

• chronione

• prywatne

Najczęściej występującym rodzajem dziedziczenia jest dziedziczenie publiczne.

(7)

Relacja typu „jest”, czyli dziedziczenie publiczne

Zgodnie z tą relacją obiekt klasy potomnej jest również obiektem klasy macierzystej. Wszystko co jest możliwe do wykonania z obiektem klasy macierzystej powinno się dać zrobić z obiektem klasy potomnej.

Przykłady relacji typu jest:

Każdy dyrektor jest pracownikiem.

Każdy czworokąt jest wielokątem.

Każdy pomidor jest warzywem.

W przypadku dziedziczenia publicznego, nowa klasa dziedziczy wszystkie pola i metody klasy macierzystej. Ponadto do nowej klasy (potomnej) można dodawać nowe pola i metody charakterystyczne wyłącznie dla klasy potomnej.

(8)

dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 8/12

Polimorfizm

Klasa Dyrektor dziedziczyła po klasie Pracownik, w szczególności odziedziczyła metodę getPensja() nie wnosząc do niej żadnych zmian. Bardzo często konieczna jest jednak zmiana działań odziedziczonych metod.

W takim przypadku należy uzależnić działanie metody w zależności od klasy obiektu na rzecz którego wywoływana jest owa metoda.

Mechanizm polegający na tym, że jedna metoda może występować w wielu różnych postaciach w zależności od kontekstu jej wywołania nazywamy polimorfizmem.

W celu wdrożenia polimorficznego działania dziedziczenia publicznego stosujemy:

• redefinicje metod klasy macierzystej w klasie potomnej

• metody wirtualne

(9)

metoda virtual-na

Dla klasy Dyrektor inna wersja metody getPensja() może być postaci:

double getPensja() {

return Pracownik::getPensja() + dodatekFunkcyjny;

}

Aby odpowiednia wersja metody getPensja() została wywołana należy przed deklaracją metody umieścić słowo virtual. W części deklaracyjnej słowo virtual pomijamy.

virtual double getPensja();

W przypadku poprzedzenia deklaracji słowem virtual, odpowiednia wersja metody zostanie wywołana w oparciu o typ obiektu, do którego odwołuje się referencja lub wskaźnik.

Dyrektor anna;

Pracownik janek;

Pracownik & p1 = anna;

Pracownik & p2 = janek;

p1.getPensja(); //wywołana metoda Dyrektor::getPensja();

(10)

dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 10/12

bez virtual 

W przypadku, gdy metoda przedefiniowana nie jest poprzedzona w części deklaracyjnej słowem virtual, wówczas sposób działania metody opiera się na typie referencji, a nie na typie obiektu.

Dyrektor anna;

Pracownik janek;

Pracownik & p1 = anna;

Pracownik & p2 = janek;

p1.getPensja(); //wywołana metoda Pracownik::getPensja();

p2.getPensja(); //wywołana metoda Pracownik::getPensja();

Zazwyczaj dobrą praktyką jest poprzedzanie w klasie macierzystej słowem virtual deklaracje tych metod, które są przedefiniowane w klasie potomnej. Zabieg ten pozwala wybrać odpowiednie wersje metod, na podstawie obiektu, na rzecz którego są one wywoływane, a nie na postawie referencji lub wskaźnika.

(11)

wykorzystanie metod wirtualnych

Czasami mamy do czynienia z wieloma obiektami zarówno klasy macierzystej jak i pochodnej. W takiej sytuacji, aby działanie naszego kodu było uniwersalne, wykorzystuje się tablicę wskaźników do typu klasy macierzystej.

Pracownik * tabP[5];

tabP[0] = new Pracownik(„Jan”, „Kowalski”, „fizyczny”, 1500);

tabP[1] = new Pracownik(„Adam”, „Lis”, „fizyczny”, 1600);

tabP[2] = new Pracownik(„Joanna”, „Dzik”, „sekretarka”, 1800);

tabP[3] = new Pracownik(„Danuta”, „Kot”, „księgowa”, 2500);

tabP[4] = new Dyrektor(600,„Krzysztof”, „Borsuk”, „dyrektor”, 3500);

for (int i=0; i<5; i++) {

tabP[i]->wypiszDane();

cout << tabP[i]-> getPensja() << endl;

}

(12)

dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 12/12

KONIEC

Dziękuję za uwagę 

Cytaty

Powiązane dokumenty

Zdrowy krasnoludek zarazi się matemafilią, jeśli co najmniej dwóch jego sąsiadów jest na nią chorych (sąsiadami są krasnoludki, które zajmują pola o sąsiednim boku)..

Na okrągłym stoliku gracze kładą złotówki, przy czym nie mogą one wystawać poza stolik ani nachodzić na siebie oraz nie wolno przesuwać leżących już monet.. W

Udowodnij, że każda liczba

Czy kwadrat 8x8 można pokryć piętnastoma tetraminami w kształcie litery L (rysunek poniżej) i jednym kwadratem 2x2 tak, żeby na siebie nie nachodziły?.

Czwórka znajomych chce po ciemku przedostać się na drugą stronę tego mostu, ale mają jedynie 1 świeczkę.. Pierwszy z nich przechodzi przez most minimalnie 10 minut, drugi 5,

możesz położyć na niej ile chcesz sztabek na raz, ale tylko raz bo potem się zepsuje (nie możesz dokładać sztabek do tych już położonych na wadze).. Jak za pomocą tej

Każdy z nich liczy latarnie obracając się zgodnie z ruchem wskazówek zegara, ale zaczynają odliczanie od różnych latarni, w związku z czym czwarta latarnia według Jacka

W pewnym sklepie sprzedawane są tabliczki mlecznej, białej oraz gorzkiej czekolady, wszystkie po tej samej cenie.. Pewnego dnia przychód sklepu ze sprzedaży mlecznej czekolady