po dziedziczeniestud

background image

Programowanie Obiektowe

Materiały pomocnicze do wykładu.
Wyłącznie do użytku wewnętrznego!!!!!

Dr inż. Zbigniew Świerczyński

Dziedziczenie

Istota dziedziczenia.

Dostęp do składników

Dziedziczenie wielopokoleniowe i wielobazowe

Dziedziczenie wirtualne

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

3

Czym jest klasa i obiekt w PO?

Niezmiernie ważne jest, aby wiedzieć, że:
Klasa jest opisem cech i zachowań obiektów,

opisem tego, jak powinien wyglądać obiekt,
który będzie reprezentantem tej klasy (jej
instancją). Klasa jest pojęciem, którego
egzemplarzem jest obiekt.

Klasa nie jest zbiorem istniejących obiektów

o podobnych własnościach (atrybutach) i
identycznych zachowaniach i nie jest też
definicją takiego zbioru.

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

4

Istota dziedziczenia

Dziedziczenie to technika pozwalająca na

definiowane nowej klasy z wykorzystaniem
klasy już wcześniej istniejącej, bez zmiany tej
ostatniej.

Nowa Klasa

Stara Klasa

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

5

Istota dziedziczenia c.d.

s a m o c h ó d

o s o b o w y

V W

c ię ż a r o w y

J a g u a r

P o r s c h e

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

6

Istota dziedziczenia c.d.

• Pies domowy:

• Istota żywa
• Ograniczony wzrost
• Zdolny do samodzielnego poruszania się
• Stałocieplny
• Potrafi ssać
• Samice mają gruczoły mlekowe
• Psowaty wygląd
• Drapieżny

zw ierzę

ssa k

p ies

Pies domowy – drapieżny ssak z rodziny
psowatych, udomowiony przez człowieka
potomek wilka szarego.

• Pies domowy: ssak

• Psowaty wygląd
• Drapieżny

• Ssak: zwierzę

• Stałocieplny
• Potrafi ssać
• Samice mają gruczoły mlekowe

ko ń

background image

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

7

Dziedziczenie - przykład

• Przykład:

– Golf i lepszy Golf

Golf

GolfKlasyS

GolfKlasyS

Golf

class TCGolf {

public:

int Zbiornik;
void WlaczSilnik() {} ;

};
class TCGolfKlasyS

: public TCGolf

{

public:

int Klimatyzacja;
void WlaczSilnik() {} ;

};
//////////////////////////////////////
int main(int argc, char *argv[])
{

TCGolf Golf;
TCGolfKlasyS GolfKlasyS;

Golf.Zbiornik=20;
GolfKlasyS.Zbiornik=30;//pole odz.
GolfKlasyS.Klimatyzacja=18;

return 0;

}

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

8

Składniki odziedziczone

• Do odziedziczonych

składników
zdefiniowanych w
klasie TCGolf
możemy odnosić się
tak, jak do składników
zdefiniowanych w
klasie

TCGolfKlasyS

class TCGolf {

public:

int Zbiornik;
void WlaczSilnik() {} ;

};
class TCGolfKlasyS: public TCGolf {

public:

int Klimatyzacja;
void WlaczSilnik() {} ;

};
//////////////////////////////////////
int main(int argc, char *argv[])
{

TCGolf Golf;
TCGolfKlasyS GolfKlasyS;

Golf.Zbiornik=20;

GolfKlasyS.Zbiornik

=30; //pole

// odziedziczone

GolfKlasyS.Klimatyzacja=18;

return 0;

}

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

9

• Nazewnictwo:

Klasa podstawowa,
Klasa pochodna,

Klasa pochodna i podstawowa -
nazewnictwo i oznaczenia

Golf

GolfKlasyS

GolfKlasyS

Golf

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

10

Klasa pochodna i podstawowa

• W klasie pochodnej

możemy:

– zdefiniować nowe,

dodatkowe składowe

– zdefiniować składowe,

które już istnieją w
klasie podstawowej

class TCGolf {

public:

int Zbiornik;
void WlaczSilnik() {};

};
class TCGolfKlasyS: public TCGolf {

public:

int Klimatyzacja;
void WlaczSilnik() {};

};
//////////////////////////////////////
int main(int argc, char *argv[])
{

TCGolf Golf;
TCGolfKlasyS GolfKlasyS;

Golf.Zbiornik=20;
GolfKlasyS.Zbiornik=30;//pole odz.
GolfKlasyS.Klimatyzacja=18;

return 0;

}

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

11

Przesłanianie

• W tym drugim przypadku mamy do czynienia z

zasłanianiem (przesłanianiem) składników
klasy podstawowej.

• Występuje ono jeśli oba składniki mają tą samą

nazwę i w przypadku funkcji taką samą listę
argumentów (to nie jest przeciążanie/
przeładowanie).

class TCGolf {

public:

void WlaczSilnik() {};

};
class TCGolfKlasyS: public TCGolf {

public:

void WlaczSilnik() {};

};

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

12

Przesłanianie c.d.

• Wskutek dziedziczenia mamy do czynienia

z jakby zagnieżdżaniem się zakresów.

• Poniższy zapis spowoduje wywołanie elementu

z klasy pochodnej

{ // zakres klasy podstawowej

int x;

//składnik przesłaniany

int k;
{// zakres klasy pochodnej

int x;

//składnik przesłaniający

int m;

}

}

int main(int argc, char *argv[])
{
...

GolfKlasyS.WlaczSilnik();

}

background image

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

13

Dostęp do przesłoniętej składowej

• Jeśli zależy nam na

wywołaniu elementu
klasy podstawowej,
to musimy użyć
operatora zakresu
(kwalifikatora
zakresu
) czyli
nazwy
kwalifikowanej

int main(int argc, char *argv[])
{
...

// Własna

GolfKlasyS.WlaczSilnik();

// Odziedziczona

GolfKlasyS.

TCGolf::

WlaczSilnik();

...
}

//-----------------------------------------

//wewnątrz klasy pochodnej
skladnik(); // z klasy pochodnej

przodek::

skladnik(); // z klasy podstawowej

// na zewnątrz
obiekt.skladnik(); // z klasy pochodnej
obiekt.

przodek::

skladnik();//z klasy podst.

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

14

Dostęp do składników klasy

• Tworząc klasę decydujemy o tym:

– które składowe dostępne są na zewnątrz klasy

(public) a które nie (private i protected)

– które składowe chcemy przekazać klasie

dziedziczącej (public i protected) a które nie
(private)

• Tworząc klasę pochodną dodatkowo

decydujemy poprzez specyfikator dostępu w
jakim obszarze umieścić dziedziczone składowe

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

15

Jak dziedziczone są składowe?

//Klasa podstawowa
class TCKlasaA {
public:

// dostępne dla wszystkich, nawet dla zewnętrznych

int PubA;

private:

// dostępne dla elementów klasy i zaprzyjaźnionych

int PrivA;

protected:

// dostępne dla elementów klasy i potomków

int ProtA;

};
//***********************************************************
//Klasa pochodna - dziedziczenie publiczne
class TCKlasaB:

public

TCKlasaA {

public:

int PubB;

// int PubA; // !!! To będzie odziedziczone z klasy TCKlasaA

private:

int PrivB;

protected:

int ProtB;

// int ProtA; // !!! To będzie odziedziczone z klasy TCKlasaA

};
//Klasa pochodna - dziedziczenie prywatne
class TCKlasaC:

private

TCKlasaA { .... };

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

16

Jak dziedziczone są składowe?

• Składowe prywatne też są dziedziczone, ale nie ma do

nich bezpośredniego dostępu w klasie pochodnej

.

Dziedziczenie

private

public

protected

private

public

protected

private

private

z klasy bazowej

Klasa podstawowa

Klasa pochodna

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

17

Domyślny specyfikator dostępu

• Do składowych prywatnych klasy podstawowej

można dostać się poprzez publiczną funkcję z
tej kasy. Funkcja ta będzie dostępna w klasie
pochodnej.

• Brak specyfikatora dostępu powoduje

przyjęcie domyślnego specyfikatora, którym
jest private

class przodek { ... };

class

dziedzic: przodek

{ ... }; //

Brak

class

dziedzic:

private

przodek

{ ... };

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

18

Udostępnianie wybiórcze

• Udostępnianie wybiórcze

można zastosować przy

dziedziczeniu

private

lub

protected

,

• Jest to zastosowanie

dziedziczenia publicznego

(public) w stosunku do

wybranych składowych.

• Robimy to przy pomocy

deklaracji dostępu:

KlasaPodst::Skladnik

class TCKlasaA {

public:

int poleAPubl;

protected:

int metodaAProt(int aArg);

private:

int poleAPriv;

};

class TCKlasaB: private TCKlasaA {

public:

int poleBPubl;
TCKlasaA::poleAPubl;

// deklaracja dostępu

protected:

int poleBProt;
TCKlasaA::metodaAProt;

// deklaracja dostępu

private:

int poleBPriv;

}

background image

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

19

Deklaracja dostępu - uwagi

– Umieszczona jest w klasie pochodnej
– Nie pisze się typów a jedynie nazwę (tak samo z

funkcjami)

– Sposób ten ma pewne mankamenty np. brak

rozróżnienia nazw przeciążonych.

– Może ona tylko powtórzyć dostęp a nie zmienić

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

20

Co nie jest dziedziczone?

1. Konstruktory

2. Operator przypisania (operator=)

3. Destruktor

4. Przyjaźń

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

21

Dziedziczenie wielo-pokoleniowe

• Dla klasy C:

– Klasa B jest klasą podstawową lub

podstawową bezpośrednio

– Klasa A jest klasą podstawową

pośrednio lub bazową

Lista pochodzenia jest listą klas

podstawowych bezpośrednich

• W takiej strukturze łatwo można

zauważyć co robi dziedziczenie

prywatne

Blok A

Blok B

Blok C

class A { ... };
class B: public A {...};
class C: public B {...};

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

22

Co nam daje dziedziczenie?

s a m o c h ó d

o s o b o w y

V W

c i ę ż a r o w y

J a g u a r

P o r s c h e

• oszczędność pracy (aby użyć klasy do stworzenia nowej, nawet

nie musimy wiedzieć jak ona dokładnie działa);

• budowanie hierarchii (odwzorowywanie struktury rzeczywistych

obiektów);

• klasy ogólne (takie, które służyć mają wyłącznie do

dziedziczenia);

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

23

Jak inicjalizować klasy pochodne?

• Wiemy, że konstruktory nie są dziedziczone;
• Jak powinniśmy inicjować składniki, które

odziedziczyliśmy, zwłaszcza jeśli jest ich bardzo dużo
i nie wszystkie nas interesują?

• Co jeśli jednym z elementów klasy jest obiekt jakiejś

innej klasy niezwiązanej ściśle z tą klasą?

• Odnośnie części dziedziczonej można powiedzieć, że

stanowi ona w pewnym sensie obiekt klasy
podstawowej i tak też jest traktowana.

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

24

W jakiej kolejności wywoływać się
będą konstruktory?

• Ogólnie:

Klasa wywoła najpierw swoich przodków, potem gości

a dopiero na samym końcu siebie.

• Konstruktory mogą inicjalizować komponenty swych

klas poprzez listę inicjalizacyjną.

• Konstruktory klas pochodnych mogą na tej liście

umieszczać również konstruktory klasy podstawowej

(tylko bezpośredniej).

– Jeśli nic nie wyspecyfikujemy na liście to:

• jeśli jest konstruktor domniemany (nie wymagający parametrów), to

on się wykona

• jeśli nie ma konstruktora domniemanego a jest inny, to kompilator

pokaże błąd.

background image

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

25

W jakiej kolejności wywoływane są
konstruktory? Przykład

p o j a z d

s a m o c h ó d

s i l n i k

M e r c e d e s

k l i m a t y z a c j a

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

26

W jakiej kolejności wywoływane są
konstruktory? Przykład c.d.

class TCSilnik {

int typ;
TCSilnik(int n): typ(n) { };

~TCSilnik(){ };

};
class TCKlimatyzacja {

TCKlimatyzacja (){ };

~TCKlimatyzacja (){ };

};
class TCPojazd {

TCPojazd(){ } ;

~ TCPojazd(){ } ;

};
class TCSamochod: public TCPojazd {

TCSilnik Silnik;
TCSamochod (int typ): Silnik(typ), TCPojazd() { } ;

~ TCSamochod (){ } ;

};
class TCMercedes: public TCSamochod {

TCKlimatyzacja

Klimatyzacja;

TCMercedes(int typ): Klimatyzacja(), TCSamochod(typ) { };

~ TCMercedes(){ } ;

};

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

27

Zasada:

1. najpierw wywołany będzie konstruktor klasy

podstawowej

2. następnie konstruktory gości (w kolejności

występowania na liście)

3. w dalszej kolejności wszystkie pozostałe inicjalizacje

z listy

4. w końcu konstruktor bieżącej klasy

Destrukcja obiektu dokonuje się w odwrotnej
kolejności do jego konstrukcji.

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

28

Przypisanie i inicjalizacja obiektów
klas pochodnych

• Jest to trochę skomplikowane, ponieważ wiadomo, że

nie jest dziedziczony konstruktor kopiujący (żaden nie
jest dziedziczony) ani też operator przypisania.

• Praca polegająca na przypisaniu (lub inicjalizacji)

składa się z dwóch części:

– przypisanie (lub inicjalizacja) dla części odziedziczonej
– przypisanie (lub inicjalizacja) dla części nowej (pochodnej)

• Klasa pochodna może mieć zdefiniowane konstruktor

kopiujący i/lub operator przypisania, które prace te
wykonają.

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

29

Brak zdefiniowanego operatora
przypisania

• Jeśli jednak w klasie pochodnej nie będzie

zdefiniowanego operatora przypisania,

– wtedy kompilator automatycznie wygeneruje

operator:

klasa & klasa::operator=(klasa &);

przypisujący „składnik po składniku” korzystając

dla części dziedziczonej z operatora klasy

podstawowej

• jeśli operator klasy podstawowej jest prywatny, wtedy nie

będzie generował tego operatora dla klasy pochodnej

• jeśli klasa ma jakiś składnik const lub będący

referencją wtedy operator nie będzie wygenerowany

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

30

Brak zdefiniowanego konstruktora
kopiującego

• Jeśli w klasie pochodnej nie będzie

zdefiniowanego konstruktora kopiującego,

– wtedy kompilator automatycznie wygeneruje

konstruktor:

klasa::klasa(klasa &);

kopiujący „składnik po składniku” korzystając dla

części dziedziczonej z konstruktora kopiującego

klasy podstawowej

• jeśli konstruktor kopiujący klasy podstawowej jest

prywatny, wtedy nie będzie generował tego konstruktora

dla klasy pochodnej

background image

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

31

Samodzielna inicjalizacja

• Napisanie samodzielne w klasie pochodnej

konstruktora kopiującego oraz operatora przypisania

nie powinno nastręczać trudności, ponieważ

wykorzystuje się przy tym poznaną już wiedzę. Pewien

drobny problem może stanowić wywołanie operatora

przypisania z klasy bazowej na rzecz obiektu klasy

pochodnej. Jeden ze sposobów polega na jawnym

wywołaniu czyli:

(*this).przodek::operator=(wzor);

gdzie wzor to zmienna zawierająca wzorcowe wartości

określona jako: potomek &wzor;

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

32

Dziedziczenie wielokrotne
(wielobazowe)

• Dziedziczenie wielokrotne uzyskuje się

umieszczając na liście dziedziczenia
(pochodzenia)
więcej niż jedną klasę
podstawową.

samochód

łódka

amfibia

class samochod { ... };
class lodka { ... };
class amfibia

: public samochod, public lodka

{ ... };

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

33

O czym trzeba pamiętać?

• Przy dziedziczeniu wielobazowym należy

pamiętać, że:

– każda klasa może pojawić się na liście tylko raz
– definicja klasy umieszczonej na liście musi być już

wcześniej znana

– na liście przed każdą nazwą klasy musi wystąpić

określenie sposobu dziedziczenia

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

34

Przykład

class samochod
{
protected :

int a ;

public:

samochod(int arg) : a(arg) {

cout << "Konstruktor samochodu\n" ;

} ;

} ;
/////////////////////////////////////////////////////////
class lodka {
protected :

int b ;

public:

lodka(int x) : b(x) {

cout << "Konstruktor lodki \n" ;

}

} ;
/////////////////////////////////////////////////////////
class amfibia :

public samochod, public lodka

//

{
public :

amfibia() : samochod(1991) , lodka(4) {

cout << "Konstruktor amfibii \n" ;

}
void pisz_skladniki() {

cout << "Oto odziedziczone skladniki\na = "

<< a << "\t b = " << b << endl ;

}

} ;
/*******************************************************/
main()
{ amfibia aaa ;

aaa.pisz_skladniki();

}

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

35

Wieloznaczność

Jak temu zaradzić (2 sposoby):

• pisać nazwy kwalifikowane:

samochod::x lub lodka::x

• zdefiniować składnik (w amfibii) o tej samej nazwie

int amfibia ::x() { return samochod::x; }

samochód (a,

x

)

łódka

(b,

x

)

amfibia

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

36

Wieloznaczność - poszlaki

• Zapis: ojciec::x,

wskazuje gałąź poszukiwań.

ojciec

matka

(

x

)

dziecko

dziadek

(

x

)

background image

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

37

Konwersje standardowe przy
dziedziczeniu

• Wskaźnik (referencja) do obiektu klasy

pochodnej może być niejawnie przekształcony
na wskaźnik (referencję) dostępnej
jednoznacznie klasy podstawowej.

• Dotyczy to wskaźników i referencji a nie

obiektów

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

38

Konwersje standardowe - Przykład

class samochod { // klasa podstawowa
public:

int zbiornik;

} ;
/////////////////////////////////////////////////////////
class VW: public samochod {// klasa pochodna

//...

} ;
/////////////////////////////////////////////////////////
void StacjaBenzynowa(samochod &klient)
{

klient.zbiornik = 50;

}
/*******************************************************/
main()
{
samochod jakisSamochod;
VW VWMoj

StacjaBenzynowa(jakisSamochod);
StacjaBenzynowa(VWMoj); // niejawna konwersja
StacjaBenzynowa((samochod &)VWMoj); // jawna konwersja

}

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

39

Co jest możliwe a co nie?

pochodna obj

podstawowa obj

pochodna *wsk

podstawowa *wsk

pochodna **wskwsk

podstawowa **wskwsk

pochodna *tabWsk[]

podstawowa *tabWsk[]

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

40

Wirtualne klasy podstawowe

• Często mówi się „wirtualna klasa podstawowa”,

ale to tylko dziedziczenie jest wirtualne

B

C

D

A

A

B

C

D

A

class A {...};
class B: public virtual A {...};
class C: public virtual A {...};
class D: public B, public C {...};

class B: private virtual A {...};
class C: public virtual A {...};

class A {...};
class B: public A {...};
class C: public A {...};
class D: public B, public C {...};

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

41

Wirtualne klasy podstawowe

• Wystarczy, że jedno dziedziczenie jest

publiczne aby klasa A była dostępna publicznie

• Ciekawe jest w jaki sposób wywoływane są

konstruktory klas dziedziczonych wirtualnie

class A {...};
class B: private virtual A {...};
class C: public virtual A {...};
class D: public B, public C {...};

Funkcje wirtualne

Polimorfizm

Funkcje czysto wirtualne. Klasy abstrakcyjne

Wirtualny destruktor

background image

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

43

Wprowadzenie

• Kilka klas ma jednego przodka:

– Janek, Kasia i Fiona mają tego samego ojca
– Mercedes, Fiat i Volvo są to samochody
– Trąbka, bęben i fortepian to instrumenty

trąbka

fortepian

bęben

instrument

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

44

Przykład

class instrument { // Klasa podstawowa
public:

void virtual wydaj_dzwiek() {

cout << "Nieokreslony brzdek !\n" ;

}

};
/////////////////////////////////////////////////////////
class trabka : public instrument {
public:

void wydaj_dzwiek()

{

cout << "Tra-ta-ta !\n" ;

}
// ...

} ;
/////////////////////////////////////////////////////////
class beben: public instrument {
public:

void wydaj_dzwiek() {

cout << "Bum-bum-bum !\n" ;

}
// ...

} ;
/////////////////////////////////////////////////////////
class fortepian : public instrument {
public:

void wydaj_dzwiek() {

cout << "Pilm-plim-plim !\n" ;

}
// ...

} ;
/////////////////////////////////////////////////////////

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

45

Przykład c.d.

void muzyk(instrument & powierzony_instrument) {

powierzony_instrument.wydaj_dzwiek(); }

/*******************************************************/
main()
{ //

Obiekty

instrument jakis_instrument ;
trabka zlota_trabka ;
fortepian steinway_giseli ;
beben moj_werbel ;

jakis_instrument.wydaj_dzwiek();
zlota_trabka.wydaj_dzwiek();
steinway_giseli.wydaj_dzwiek();
moj_werbel.wydaj_dzwiek();

instrument *wskinstr ;

// ustawianie wskaźnika

wskinstr = & jakis_instrument ;
wskinstr-> wydaj_dzwiek() ;
wskinstr = &zlota_trabka ;
wskinstr-> wydaj_dzwiek() ;
wskinstr = &steinway_giseli ;
wskinstr-> wydaj_dzwiek() ;
wskinstr = &moj_werbel ;
wskinstr-> wydaj_dzwiek() ;

// poprzez referencję

muzyk(jakis_instrument);
muzyk(zlota_trabka);
muzyk(steinway_giseli) ;
muzyk(moj_werbel) ;

}

Tra-ta-ta

Tra-ta-ta

Bum-bum-bum

Pilm-plim-plim

Pilm-plim-plim

Bum-bum-bum

Nieokreślony brzdęk

Nieokreślony brzdęk

Tra-ta-ta

Bum-bum-bum

Pilm-plim-plim

Nieokreślony brzdęk

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

46

Wielopostaciowość

• Dzięki funkcji wirtualnej (modyfikacji w deklaracji

funkcji słowem virtual)

• instrukcja zapisana jako

Referencja.wydaj_dźwięk();

• interpretowana jest w trakcie działania programu jako:

Referencja.instrument::wydaj_dźwięk();
Referencja.trabka::wydaj_dźwięk();
Referencja.fortepian::wydaj_dźwięk();

• Identyczny efekt osiągamy dla wskaźników

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

47

Polimorfizm

• Taka wielość form określana jest mianem

polimorfizm czyli inaczej wielopostaciowość.
Ale to nie funkcja wirtualna jest polimorficzna
tylko takie jej wywołanie wykazuje
polimorfizm lub zachowuje się polimorficznie.

• Dzieje się to kosztem rozmiaru wynikowego

programu oraz jego szybkości.

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

48

Polimorfizm c.d.

• Wczesne i późne wiązanie

– Wczesne wiązanie to wiązanie na etapie kompilacji
– Późne wiązanie to wiązanie na etapie wykonywania

• Polimorfizm nie jest

przeciążeniem/przeładowaniem

background image

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

49

Funkcja wirtualna

Funkcja składowa jest wirtualna wtedy, gdy w

definicji klasy przy jej deklaracji stoi słowo virtual,

lub gdy w jednej z klas podstawowych tej klasy

identyczna funkcja zadeklarowana jest jako virtual.

• Klasa pochodna nie musi definiować swojej wersji

funkcji wirtualnej.

• Funkcja wirtualna

– nie może być static.
– Może być zaprzyjaźniona z jakąś inną klasą, ale nie będzie

dla niej wirtualną

– Może być inline (ale czasem będzie to ignorowane)

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

50

Klasy abstrakcyjne

• To klasa, która nie reprezentuje żadnego

konkretnego obiektu i służy tylko do

dziedziczenia

• Skoro klasa abstrakcyjna nie reprezentuje

żadnego obiektu, więc nie będziemy tworzyć na

jej podstawie żadnego obiektu. Jeśli klasa ta

zawiera funkcję wirtualną to funkcja ta nie

będzie realizowana i można ją zdefiniować

następująco

Typ virtual funkcja() = 0 ;

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

51

Funkcja czysto wirtualna

• Funkcję taką nazywamy czysto wirtualną (ang. pure

virtual). Oznacza to, że tej wersji funkcji wirtualnej nie
ma się nigdy wykonywać.

• Zdefiniowanie w jakieś klasie funkcji czysto wirtualnej

powoduje, że kompilator nie pozwoli na stworzenie
obiektu tej klasy. Klasa ta jest abstrakcyjna nie tylko
dla nas ale i dla kompilatora.

• Brak definicji funkcji w klasie pochodnej powoduje

odziedziczenie funkcji czysto wirtualnej ze wszystkimi
tego skutkami (brak możliwości tworzenia obiektów).

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

52

Wirtualny destruktor

• Mimo iż wyda się to dziwne, to jednak

wirtualność destruktora jest możliwa

• Można uzasadnić to tym, że

– w klasie jest tylko jeden
– nigdy nie ma parametrów
– można przyjąć, że nazwa się zawsze „destruktor”

• Wirtualność destruktora jest wyjątkiem.

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

53

Po co wirtualny destruktor?

• Wprowadzenie funkcji wirtualnych oznacza, że chce się

korzystać polimorfizmu

• Polimorfizm to możliwość odnoszenia się do obiektów klas

pochodnych poprzez wskaźnik (lub referencję) do klasy
bazowej.

• Poza wywołaniem metody wirtualnej często zachodzi też

potrzeba zniszczenia takiego obiektu (wskazywanego przez
wskaźnik do klasy bazowej).

• Jeśli mówimy „umyj ten pojazd” mając na myśli konkretny

obiekt (np. Volvo), to możemy też powiedzieć „zniszcz ten
pojazd” i to też odnosi się do tego konkretnego, który
wskazujemy.

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

54

Po co wirtualny destruktor? Przykład

• Przy tworzeniu różnych

obiektów wywoływane

są różne konstruktory

• Różne obiekty

wskazywane są przez

taki sam wskaźnik

• Wywołanie różnych

funkcji przez taki sam

wskaźnik

• Wywołanie różnych

destruktorów przez taki

sam wskaźnik

main()
{
//Jednakowe wskaźniki ale
// różne konstruktory

instrum *pierwszy = new skrzypce;
instrum *drugi = new gitara; //
instrum *trzeci = new gwizdek ;

//Różne funkcje

pierwszy->wydaj_dzwiek() ;
drugi ->wydaj_dzwiek() ;
trzeci ->wydaj_dzwiek() ;

//Jednakowe wskaźniki ale
//muszą być różne destruktory

delete pierwszy ;
delete drugi ;
delete trzeci ;

}

background image

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

55

Jak uzyskać wirtualny destruktor?

• Tę sprawę załatwia postawienie słowa virtual przed

nazwą destruktora

• Dzięki temu destruktor będzie wywoływany

inteligentnie, co spowoduje, że niszczony będzie
właściwy obiekt w całości (a nie tylko jego część
odpowiadająca klasie podstawowej).

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

56

Zasada

Jeśli klasa deklaruje jedną ze swych
funkcji jako virtual,
wówczas jej destruktor deklarujemy
również jako virtual.

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

57

Wirtualny destruktor - przykład

class instrum {
public :

void virtual wydaj_dzwiek() {

cout << "cisza" ;

}

virtual ~instrum() { // ----wirtualny destruktor

cout << "Destruktor instrumentu \n" ;

}

} ;
/////////////////////////////////////////////////////////
class skrzypce : public instrum { //

char *nazwa ;

public :

skrzypce(char *firma) {// - konstruktor------------

nazwa = new char[strlen(firma) + 1] ; //
strcpy(nazwa, firma) ;

}
~skrzypce() { //- destruktor (wirtualny) -------------

cout << "Destruktor skrzypiec + " ;
delete nazwa ; //

}
// ----------------------------
void wydaj_dzwiek()
{

cout << "tirli-tirli ("

<< nazwa << ")\n" ;

}

} ;

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

58

Wirtualny destruktor - przykład

class gwizdek :public instrum { //
public :

void wydaj_dzwiek() {

cout << "fiu-fiu \n" ;

}

} ;
/////////////////////////////////////////////////////////
class gitara : public instrum {

char *nazwa ;

public :

gitara(char *firma) {// - konstruktor-----------------

nazwa = new char[strlen(firma) + 1] ; //
strcpy(nazwa, firma) ;

}
~gitara() { //- destruktor (wirtualny) ---------------

cout << "Destruktor gitary + " ;
delete nazwa ; //

}
// --------------------------
void wydaj_dzwiek()
{

cout << "brzdek-brzdek ("

<< nazwa << ")\n" ;

}

} ;

K

ATEDRA

M

ETROLOGII

E

LEKTRONICZNEJ

I F

OTONICZNEJ

opracowanie Zbigniew Świerczyński

59

Wirtualny destruktor - przykład

main()
{

cout << "Definiujemy w zapasie pamięci\n"

"trzy instrumenty orkiestry\n " ;

instrum *pierwszy = new skrzypce("Stradivarius") ;
instrum *drugi = new gitara("Ramirez") ;
instrum *trzeci = new gwizdek ; //

cout << "Gramy polimorficznie ! \n" ;

pierwszy->wydaj_dzwiek() ; //
drugi ->wydaj_dzwiek() ;
trzeci ->wydaj_dzwiek() ;

cout << "\nKoncert sie skonczyl, "

"likwidujemy instrumenty\n\n" ;

delete pierwszy ; //
delete drugi ;
delete trzeci ;

}
/*******************************************************/


Wyszukiwarka

Podobne podstrony:
przewodnik po przepisach w dziedzinie pomocy państwa
Darowizna i dziedziczenie mieszkania, dożywocie, wstąpienie w najem po śmierci wynajmującego
Jacek Dziedzina – Po coś tu jestem
Córki dziedziczą po matkach char bud ukł kortolimbicznego
Ludzie mogą dziedziczyć mitochondrialne DNA po ojcu
PO wyk07 v1
Rehabilitacja po endoprotezoplastyce stawu biodrowego
Systemy walutowe po II wojnie światowej
HTZ po 65 roku życia
Rodowody, dziedziczenie, imprinting
Zaburzenia wodno elektrolitowe po przedawkowaniu alkoholu
Organy po TL 2
dziedziczenie chorob jednogenowych
Metoda z wyboru usprawniania pacjentów po udarach mózgu
03Operacje bankowe po rednicz ce 1
Piramida zdrowia po niemiecku

więcej podobnych podstron