Projekt 01, Wykład 01

background image

Polimorfizm

†

Dziedziczenie wielokrotne

†

Funkcje wirtualne

†

Klasy abstrakcyjne

†

Mechanizm polimorfizmu

background image

Dziedziczenie wielokrotne

†

Dziedziczenie wielokrotne zachodzi wtedy,

jeżeli klasa ma więcej niż jedną klasę

podstawową, dziedziczoną bezpośrednio

†

Używane jest znacznie rzadziej niż

jednokrotne

†

Zastosowanie:

„

Jeżeli zachodzi potrzeba powiązania ze sobą

niezależnych klas

„

Jeżeli klasa pochodna ma cechy dwóch lub

więcej już zdefiniowanych klas

background image

Przykład dziedziczenia

wielokrotnego

†

Kod programu:

class TSamochod {

//PIERWSZA KLASA PODSTAWOWA

int Kolo[4];

...};

class TLodka {

//DRUGA KLASA PODSTAWOWA

float Ster;

...};

class TAmfibia: public TSamochod, public TLodka {

//...

};

TSamochod

TLodka

TAmfibia

background image

Uwagi dotyczące dziedziczenia

wielokrotnego

†

Każda klasa podstawowa jest wymieniana

jednokrotnie. Nie jest dopuszczalna np.

deklaracja

class TAmfibia: TSamochod,TLodka,TSamochod {};

†

Każda z klas podstawowych ma własny

sposób dziedziczenia

„

Modyfikatory: public, protected, private

„

Domniemany jest private, jak przy dziedziczeniu

jednokrotnym

„

Nie wpisanie modyfikatora przed nazwą każdej

klasy podstawowej oznacza dziedziczenie private

†

Definicje wszystkich klas podstawowych

muszą być umieszczone przed deklaracją

klasy pochodnej

background image

Konstruktor klasy pochodnej przy

dziedziczeniu wielokrotnym

†

Konstruktor klasy pochodnej powinien

zawierać wywołania konstruktorów klas

podstawowych bezpośrednio w liście

inicjalizacyjnej

†

Wywołanie można pominąć, jeżeli klasa

podstawowa ma konstruktor domniemany

†

Konstruktory klas podstawowych są

wywoływane w kolejności umieszczenia na

liście pochodzenia w deklaracji klasy

†

Konstruktory obiektów składowych są

wywoływane w kolejności umieszczenia na

liście inicjalizacyjnej klasy

background image

Wieloznaczność przy dziedziczeniu

wielokrotnym

class TPierwsza {

int a;

float x;};

class TDruga {

int a;

float b;};

class TPochodna: public TPierwsza, public TDruga

{

//void Wypisz(void){ cout << a; }; //???

};

†

W jaki sposób można uzyskać dostęp do

składnika a w klasie pochodnej ? (Składnik ten

powtarza się w wielu klasach podstawowych)

background image

Sposoby dostępu do składnika

wieloznacznego

1) Posłużenie się operatorem zakresu w klasie

TPochodna:

„

cout << TPierwsza::a;

„

cout << TDruga::a;

†

Wady takiego rozwiązania

„

W ewentualnych klasach pochodnych od

TPochodna nadal występuje wieloznaczność

składnika a;

„

Dotyczy to WSZYSTKICH kolejnych klas

pochodnych

„

Jeżeli wieloznaczna jest nazwa funkcji

wirtualnej, przy powyższym wywołaniu zostaje

zablokowany mechanizm wywoływania tych

funkcji (polimorfizm)

background image

Sposoby dostępu do składnika

wieloznacznego

2) Zdefiniowanie w klasie pochodnej funkcji o

nazwie jak składnik w klasie podstawowej:

„

TPochodna ... {

„

int a(){ return TPierwsza::a };

†

Zalety:

„

przestają być aktualne wady rozwiązania

pierwszego

†

Wady:

„

a jest teraz funkcją, więc przy odniesieniu się

należy stosować nawiasy:
cout << a();

background image

Bliższe pokrewieństwo

a wieloznaczność

†

Cecha nie działa w kompilatorze

Borland C++ 3.1

TZerowa
int b;

TPochodna

void W(){ cout << b; };

TPierwsza
int xxx;

TDruga
int b;

background image

Standardowe konwersje przy

dziedziczeniu

†

Jeżeli

„

Klasa jest dziedziczona publicznie

„

Konwersja jest jednoznaczna

†

Wskaźnik obiektu klasy pochodnej może być

przekształcony na wskaźnik jednoznacznie dostępnej

klasy podstawowej

( wskaźnikiem do obiektu klasy podstawowej można

pokazywać obiekt klasy pochodnej )

†

Referencja obiektu klasy pochodnej może być

przekształcona na referencję jednoznacznie dostępnej

klasy podstawowej

( referencja obiektu klasy podstawowej może być

wykorzystana do obiektu klasy pochodnej )

background image

Sytuacje gdy następuje konwersja

standardowa

†

Przesłanie obiektu do funkcji przez wskaźnik lub

referencję (poprzedni przykład) UWAGA! nie można

przesłać przez wartość !

†

Rezultat zwracany przez funkcję – jeżeli funkcja ma

zwracać wskaźnik do obiektu klasy podstawowej, po

słowie return można wpisać wskaźnik do obiektu klasy

pochodnej

†

Przeładowany operator pracujący na referencji do

obiektu klasy podstawowej może być zastosowany dla

obiektu klasy pochodnej

†

Podczas inicjalizacji obiektu klasy podstawowej

(konstruktor kopiujący) jako wzorzec można podać

obiekt klasy pochodnej

background image

Klasy wirtualne

†

Dziedziczenie wirtualne stosujemy wtedy,

gdy chcemy mieć lokalny punkt dzielenia

się informacją

TZerowa

TPochodna:

TPierwsza, TDruga, TZerowa

TPierwsza

TDruga

TZerowa

background image

Sposób deklaracji wirtualnej klasy

podstawowej

†

W liście pochodzenia należy wpisać słowo

virtual przed nazwą klasy

†

Klasa może być równocześnie dziedziczona

wirtualnie i niewirtualnie

†

Deklaracje:

class TPierwsza: public virtual TZerowa

{. . .};

class TPochodna: public TPierwsza,

public TDruga, public virtual TZerowa
{. . .};

background image

Funkcje wirtualne

†

Definicja słowa wirtualny – teoretycznie

możliwy, mogący zaistnieć

†

Funkcja wirtualna zdefiniowana w klasie

podstawowej może być ponownie zdefiniowana

w klasie potomnej

†

To ponowne zdefiniowanie w odróżnieniu od

zasłaniania nazw jest „inteligentne”

†

Mechanizm funkcji wirtualnych ma

zastosowanie, gdy obiekt jest

pokazywany wskaźnikiem, lub dostępny

przez referencję, a jego typ nie zgadza się

z typem wskaźnika

background image

Polimorfizm

†

Polimorfizm (gr. wielość postaci, form) jest

to mechanizm wywoływania funkcji

zadeklarowanych jako wirtualne

†

Jeżeli funkcja nie jest wirtualna, wtedy

wskaźnik do klasy podstawowej lub

referencja do obiektu tej klasy wywoła

funkcję Z KLASY PODSTAWOWEJ

†

W przypadku funkcji wirtualnej może zostać

wywołana funkcja z klasy pochodnej

nawet, jeżeli np. moduł z definicją klasy

podstawowej jest w postaci skompilowanej

background image

Zalety stosowania polimorfizmu

†

Dodanie do programu nowej klasy,

dziedziczonej z klasy już istniejącej nie

wymaga dokonywania poprawek we

wszystkich miejscach, gdzie mamy do

czynienia ze wskaźnikiem lub referencją do

obiektów klasy podstawowej

†

W ten sposób program może być łatwo

rozbudowywany

†

Świadczy to o rozszerzalności kodu

programu w języku C++

background image

Koszty stosowania polimorfizmu

†

Pytanie: dlaczego wszystkie funkcje

składowe obiektów nie są wirtualne?

„

Obiekt klasy zawierającej funkcje

wirtualne zajmuje więcej pamięci

„

Operacje na takim obiekcie przebiegają

wolniej

„

Mechanizmy polimorfizmu mają

praktyczne zastosowanie w połączeniu z

dziedziczeniem

background image

Właściwości funkcji wirtualnych

†

Funkcja staje się wirtualną jeżeli

„

W deklaracji zostanie użyte słowo virtual

„

W klasie podstawowej zostało użyte słowo
virtual

dla identycznej* funkcji

†

Słowo virtual nie musi (ale może)
powtarzać się w klasach pochodnych

†

Słowo virtual piszemy tylko przy
deklaracji klasy, nie pojawia się w definicji

*Funkcja identyczna = taka sama nazwa, parametry

i typ wartości zwracanej

background image

Dodatkowe informacje

†

Jeżeli funkcja wirtualna ma inny zakres

widoczności w klasie podstawowej a inny w

pochodnej, wtedy o dostępie decyduje

klasa wskaźnika (referencji)

†

Funkcje wirtualne nie mogą być statyczne

(static)

†

Funkcje wirtualne mogą być używane przez

funkcje lub klasy zaprzyjaźnione

background image

Wczesne i późne wiązanie

†

Wiązanie – połączenie wywołań funkcji

z adresami tych funkcji w pamięci

(instrukcja skoku do podprogramu)

„

Jeżeli nie są wykorzystywane funkcje

wirtualne następuje tzw. wczesne wiązanie

(ang. early binding) – podczas kompilacji

„

Jeżeli są wykorzystywane funkcje wirtualne

następuje tzw. późne wiązanie (ang. late

binding) – podczas wykonywania programu

background image

Funkcja wirtualna a inline

†

Kod funkcji inline jest bezpośrednio

wstawiany do kodu programu na etapie

kompilacji

†

Funkcje wirtualne MOGĄ BYĆ inline

„

Jeżeli wywołanie funkcji jest polimorficzne

(późne wiązanie) inline jest ignorowane

„

W przypadku wczesnego wiązania

(bezpośrednie wywołanie funkcji z obiektu)

funkcja jest traktowana jako inline

background image

Klasy abstrakcyjne

†

Klasa abstrakcyjna to klasa podstawowa,

która nie reprezentuje żadnego

konkretnego obiektu

„

Przykład: ssak, figura, bryła

†

Klasy abstrakcyjne są przeznaczone

wyłącznie do dziedziczenia

†

Mechanizm polimorfizmu bardzo często

jest łączony z klasami abstrakcyjnymi

†

W klasie abstrakcyjnej używamy funkcji

wirtualnych jeżeli

„

Zachowanie opisane funkcją jest cechą kilku klas

potomnych (np. narysowanie figury)

„

W każdej klasie potomnej to zachowanie jest

inaczej realizowane

background image

Klasy czysto abstrakcyjne

†

W ogólnym przypadku można utworzyć

obiekt klasy podstawowej posiadającej

funkcje wirtualne

†

Aby utworzyć klasę czysto abstrakcyjną,

należy przynajmniej jedną z jej funkcji

wirtualnych zdefiniownać jako „czysto

wirtualną” (ang. pure virtual):
void virtual Funkcja()=0;

†

Klasa czysto abstrakcyjna NIE MOŻE mieć

definiowanych obiektów

background image

Cechy klas abstrakcyjnych

†

Nie można definiować obiektu takiej klasy

„

np. TFigura F;

†

Nie można zdefiniować funkcji, której

argumentem byłby obiekt tej klasy

przekazywany przez wartość

„

np. void Funkcja(TFigura F);

†

Nie można zdefiniować funkcji zwracającej

obiekt takiej klasy

†

Nie można stosować nazwy klasy czysto

abstrakcyjnej do jawnej konwersji

background image

Destruktor wirtualny

†

Jeżeli w klasie występuje przynajmniej jedna

funkcja wirtualna, destruktor tej klasy

powinien być wirtualny

†

Destruktor jest wyjątkiem od ogólnej zasady

o identyczności funkcji wirtualnych

†

Destruktory wszystkich klas pochodnych od

klasy z destruktorem wirtualnym są wirtualne

†

Zadeklarowanie destruktora wirtualnego

umożliwi poprawne zwalnianie pamięci

podczas niszczenia obiektów pokazywanych

przez wskaźnik klasy podstawowej

background image

Wirtualny konstruktor ?

†

Nie można utworzyć konstruktora wirtualnego

†

Zamiast tego można zdefiniować funkcję wirtualną

która:

„

Wywoła konstruktor domniemany klasy potomnej
lub

„

Wywoła konstruktor kopiujący klasy potomnej

†

Nazwy tych funkcji mogą być dowolne

†

Funkcje zwracają wskaźnik do obiektu klasy

podstawowej

†

Można zdefiniować obie wymienione funkcje

równocześnie


Document Outline


Wyszukiwarka

Podobne podstrony:
ProjektKKa 01 Koncepcja id 4003 Nieznany
TechnologiaOdlew Projekt B 01
Dodatkowe - Projekt 01, semestr 5 - BOiJ, Technologia Remontu i Budowy Okrętu, TRiBO - Projekt (oce)
Projekt 01 Proj6b opis id 82981 Nieznany
Projekt 01, inżynieria ochrony środowiska kalisz, a pwsz kalisz ioś, IV odpady i wytrzymalosc materi
ProjektKKa 01 Koncepcja
Magazyny, Projektowanie magazynów wykład 2
FP 7 i 8, Prawo Finansowe, Wykłady IV rok - projekt, PF - wykłady, wykłady PF - 6 semestr
Projekowanie technologiczne WYKŁADY
Projekt zestaw E, wykłady, wentylacja, Minikowski
żelbet2, studia, Budownctwo, Konstrukcje betonowe Projekty Ćwiczenia Wykłady, Konstrukcje Betonowe,
Bazy danych - podstawowe kroki w projektowaniu cz 2 - wyklady, Zajęcia z Baz Danych - MS Access, cz
Bazy danych - podstawowe kroki w projektowaniu cz 2 - wyklady, Zajęcia z Baz Danych - MS Access, cz
Magazyny, Projektowanie magazynu wykład 3
Projekt przedsiebziecie wyklad2
Zagadnienia 2011, Szkoła, Politechnika 1- 5 sem, SEM IV, Komputeryzacja Projektowania w Elektronice.
Projekt 04 Wykład 4
projektowanie cd, wykłady, projektowanie dydaktyczne

więcej podobnych podstron