PO W 5 6 II ZIN id 364233 Nieznany

background image

1

Programowanie obiektowe

Wykład 5-6



Konstruktory kopiuj

ą

ce



Klasy zaprzyja

ź

nione



Wska

ź

nik this



Przeci

ąż

anie operatorów



Funkcje wirtualne



Szablony funkcji



Szablony klas

background image

2

Programowanie obiektowe



Jedną z najważniejszych postaci konstruktorów przeciążonych są tzw.
konstruktory kopiujące



Taki konstruktor tworzy kopię innego, już istniejącego wśród obiektów
danej klasy



Ogólna postać deklaracji konstruktora kopiującego:

klasa::klasa(klasa& obiekt);

lub

klasa::klasa(const klasa& obiekt);



Pozostałe argumenty konstruktora (jeśli występują) są domyślne.



Przykłady deklaracji konstruktorów kopiujących:

X::X(X&);

lub

X::X(X&, float=3.1415, int=0)

;

Konstruktor kopiujący

background image

3

Programowanie obiektowe



Konstruktorem kopiującym w danej klasie jest konstruktor, który można
wywołać z jednym argumentem typu referencja obiektu danej klasy:

klasa::klasa(klasa &)
klasa::klasa(const klasa &)



Konstruktor kopiujący wprowadza obiekty identyczne z już istniejącymi,
czyli ich kopie (konstruowanie obiektu na podstawie wzoru).



Konstruktor kopiujący może być wywołany niejawnie:

1.

W sytuacji gdy do funkcji jest przekazywany przez wartość obiekt
klasy X. Wówczas tworzona jest kopia tego obiektu.

2.

W sytuacji kiedy funkcja zwraca przez wartość obiekt klasy X.
Wtedy także tworzona jest kopia obiektu.



To, że konstruktor kopiujący podaje obiekt kopiowany przez referencję daje
mu możliwość zmiany zawartości obiektu klasy!!

Konstruktor kopiujący

background image

4

Programowanie obiektowe



Nie można pominąć referencji w konstruktorze kopiującym, bo gdyby
konstruktor X wywoływał obiekty swojej klasy X przez wartość, czyli
wytwarzałby swoją kopię, to powstaje nie zamknięta pętla tworzenia kopii.



Konstruktor kopiujący może uszkodzić oryginał!!



Zabezpieczamy się przed taką sytuacją następująco:

X::X(const X& obiekt)



Teraz konstruktor X wie, że obiekt klasy X jest jest typu const, czyli nie
może zmienić sam siebie.

Konstruktor kopiujący

background image

5

Programowanie obiektowe



Przykład programowy

Program 4.5

Konstruktor kopiujący

background image

6

Programowanie obiektowe



Są to takie funkcje, które mimo, że nie są składnikami klasy mają dostęp do
jej składników czyli innych funkcji i zmiennych danej klasy



Mają dostęp także do tych składników klasy, które są hermetyzowane
etykietą private



Funkcja zaprzyjaźniona jest wprowadzana słowem kluczowym friend



Sposób stosowania:

class figura{

int x,y;
…….
friend void goniec(figura f)

};

Funkcje zaprzyjaźnione

background image

7

Programowanie obiektowe



Funkcja goniec(figura f) jest zdefiniowana gdzieś w programie w całkowicie
innym miejscu i nie jest funkcją składową klasy figura



W klasie figura {} chcemy z niej skorzystać nawet, jeśli przynależy ona do
innej klasy (wtedy poprawnie jest taką funkcję umieścić w sekcji public w jej
klasie).



Cechy funkcji zaprzyjaźnionych:



Funkcja może być zaprzyjaźniona z kilkoma klasami



Na argumentach jej wywołania może wykonywać operacje zgodnie ze
swoją definicją



Może być napisana w zupełnie innym języku niż C++ i dlatego może
nie być funkcją składową klasy.

Funkcje zaprzyjaźnione

background image

8

Programowanie obiektowe



Ponieważ funkcja typu friend nie jest składnikiem klasy, to nie ma
wskaźnika this czyli musi się posłużyć operatorem jawnego wskaźnika lub
przypisania, aby wykonać działania (także te na składniku klasy, z którą jest
zaprzyjaźniona).



Jest deklarowana w klasie ze słowem kluczowym friend i nie podlega
etykietom hermetyzacji (public, private, protected)



Może być cała zdefiniowana w klasie i wtedy jest typu inline, ale nadal jest
funkcją zaprzyjaźnioną.



Nie musi być funkcją składową żadnej klasy, ale może nią być

Funkcje zaprzyjaźnione

background image

9

Programowanie obiektowe



Klasa może się przyjaźnić z wieloma funkcjami, które są lub nie są
składnikami innych klas;



Funkcje zaprzyjaźnione nie są przechodnie, czyli zaprzyjaźnienie nie
przenosi się

z

klasy do klasy, tzn. zaprzyjaźnienie nie podlega

mechanizmowi dziedziczenia (w tym przypadku „przyjaciel mojego
przyjaciela nie jest moim przyjacielem” );



Z zasady umieszcza się funkcje zaprzyjaźnione na początku wszystkich
deklaracji w klasie;



Dopuszcza się stosowanie słowa kluczowego friend do definiowania klas
zaprzyjaźnionych; w takim przypadku wszystkie funkcje składowe klasy
zaprzyjaźnionej mają dostęp do prywatnych składników drugiej klasy.

Funkcje zaprzyjaźnione

background image

10

Programowanie obiektowe



Przykład programowy

Program 4.6

Funkcje i klasy zaprzyjaźnione

Program 4.7

background image

11

Programowanie obiektowe

Wskaźnik this



Podczas wywoływania funkcji składowej jest do niej automatycznie
przekazywany niejawny wskaźnik do obiektu, na rzecz którego realizowane
jest wywołanie funkcji; wskaźnik ten nazywa się this



Przykład

Program 4.8



Funkcja musi odszukać obiekt, aby wykonać operację na jego rzecz. Robi to
tak, że korzysta z ukrytego wskaźnika this, który jest inicjowany w
momencie pojawienia się operatora kropki po nazwie obiektu.



Ten wskaźnik pokazuje funkcji na którym egzemplarzu (konkrecie)

obiektów klasy ma wykonać swoje czynności.

background image

12

Programowanie obiektowe

Wskaźnik this

pwr::pwr(double base, int exp)
{

b = base;
e = exp;
val = 1;
if(exp==0) return;
for( ; exp>0; exp--) val = val * b;

}

pwr::pwr(double base, int exp)
{

this->b = base;
this->e = exp;
this->val = 1;
if(exp==0) return;
for( ; exp>0; exp--)

this->val = this->val * this->b;

}

background image

13

Programowanie obiektowe

Referencje



Język C++ posiada dodatkową cechę związana ze wskaźnikami - referencję;



Zasadniczo referencja to niejawny wskaźnik;



Można ja wykorzystywać na trzy sposoby:

1)

jako parametr funkcji,

2)

jako zwracaną wartość,

3)

jako zmienną referencyjną.

background image

14

Programowanie obiektowe

Referencje jako parametry



W momencie wywołania funkcji jej parametry mogą być przekazywane na
dwa sposoby: przez wartość i przez referencję;



Podczas przekazywania parametru przez wartość do funkcji przekazywana
jest kopia argumentu;



Przykład:

Program 4.9a

background image

15

Programowanie obiektowe

Referencje jako parametry



Ważnym zastosowaniem referencji jest możliwość definiowania funkcji,
wykorzystujących mechanizm przekazywania parametrów przez referencję;



Przekazywanie przez referencję polega na przekazaniu do funkcji wskaźnika
do argumentu; można to realizować na dwa sposoby:



jawne przekazanie wskaźnika do parametru;



posłużenie się się tzw. parametrem referencyjnym;

background image

16

Programowanie obiektowe

Referencje jako parametry



Przykład jawnego przekazania wskaźnika do parametru

Program 4.10



Przykład użycia parametru referencyjnego

Program 4.9

background image

17

Programowanie obiektowe

Przekazywanie obiektów przez referencję



Przekazywanie obiektu jako argumentu funkcji polega na przekazaniu jego
kopii;



Po zakończeniu funkcji kopia jest niszczona i wywoływany jest destruktor
tej kopii;



Jeśli nie chcemy, aby destruktor był uaktywniany, możemy przekazać
obiekt do funkcji przez referencję;



Podczas przekazywania obiektu przez referencję kopia obiektu nie jest
tworzona (w konsekwencji nie ma jej niszczenia i nie jest wywoływany
destruktor obiektu);



Przykład

Program 4.11

c:

background image

18

Programowanie obiektowe

Zwracanie referencji



Funkcja może zwracać referencję;



W konsekwencji funkcja może występować z lewej strony instrukcji
przypisania!



Przykład

Program 4.12

background image

19

Programowanie obiektowe

Zmienne referencyjne



Referencję można zastosować jako samodzielna zmienną;



Zmienna referencyjna jest tworzona jako nowa nazwa dla istniejącej
zmiennej (przezwisko);



Podczas tworzenia zmiennej referencyjnej obowiązkowa jest jej inicjacja;



Przykład

Program 4.13

background image

20

Programowanie obiektowe

Przeciążanie operatorów



Z przeciążaniem funkcji ściśle związane jest zagadnienie przeciążania operatorów



W języku C++ można przeciążyć większość operatorów tak, aby wykonywały
zadania charakterystyczne dla danej klasy, np. dla klasy stos operator + może być
wykorzystany do dodawania elementu na stos, a operator do zdejmowania
elementu ze stosu



Po przeciążeniu odpowiednich operatorów można posługiwać się obiektami w
wyrażeniach tak samo jak zmiennymi typów wbudowanych



Operator można przeciążyć tworząc funkcję operatora



Funkcja operatora definiuje, jakie operacje na obiektach wskazanej klasy ma
wykonywać operator



Do tworzenia funkcji operatora służy słowo kluczowe operator



Funkcja operatora może, ale nie musi, być składową klasy



Funkcje operatora nie będące składowymi klasy są najczęściej jej funkcjami
zaprzyjaźnionymi

background image

21

Programowanie obiektowe

Przeciążanie operatorów



Ogólna składnia funkcji operatora, będącej składową klasy:

zwracany_typ nazwa_klasy::operator # (lista_argumentów)

{

//operacje

}



Lista argumentów może być pusta (w przypadku operatorów
jednoargumentowych)



Przykład

symbol operatora

Program 5.1

background image

22

Programowanie obiektowe

Przeciążanie operatorów

// Przeciążenie operatora + dla klasy loc

loc loc::operator+(loc op2) {

loc temp;
temp.longitude = op2.longitude + longitude;
temp.latitude = op2.latitude + latitude;
return temp;

}
int main() {
loc ob1(10, 20), ob2( 20, 30);

ob1.show();

// wyświetla 10 20

ob2.show();

// wyświetla 20 30

ob1 = ob1 + ob2;

...

operand przekazywany przez wskaźnik this

operand przekazywany przez parametr op2

background image

23

Programowanie obiektowe

Przeciążanie operatorów



W kolejnym programie przykładowym przeciążone zostaną trzy operatory
dwuargumentowe (+,

, =) oraz jeden operator jednoargumentowy (++)

w formie przedrostkowej



Przykład

Program 5.2

background image

24

Programowanie obiektowe

Operatory przyrostowe - przypomnienie



Przykład

#include <iostream>

using namespace std;

int main(void) {

int i, j;

i = 10;

j = i++;

/* wy

ś

wietlenie warto

ś

ci zmiennych i oraz j */

cout << "i=" << i;

cout << ", j=" << j;

getchar();

// Zatrzymanie okna konsoli

return 0;

}

Program 5.3

// Najpierw przypisanie, potem inkrementacja

background image

25

Programowanie obiektowe



Przykład

#include <iostream>

using namespace std;

int main(void) {

int i, j;

i = 10;

j = ++i;

/* Wy

ś

wietlenie warto

ś

ci zmiennych i oraz j */

cout << "i=" << i;

cout << ", j=" << j;

getchar();

// Zatrzymanie okna konsoli

return 0;

}

Program 5.4

Operatory przyrostowe - przypomnienie

// Najpierw inkrementacja, potem przypisanie

background image

26

Programowanie obiektowe



Inkrementacja w formie przedrostkowej

typ operator++() {

// ciało operatora w formie przedrostkowej

}



Inkrementacja w formie przyrostkowej

typ operator++(int x) {

// ciało operatora w formie przyrostkowej

}



Dekrementacja w formie przedrostkowej

typ operator

−−−− −−−−

() {

// ciało operatora w formie przedrostkowej

}



Dekrementacja w formie przyrostkowej

typ operator

−−−− −−−−

(int x) {

// ciało operatora w formie przyrostkowej

}

Formy przedrostkowe i przyrostkowe przeciążonych operatorów

inkrementacji i dekrementacji

Program 5.2a

background image

27

Programowanie obiektowe

Przeciążanie operatorów za pomocą funkcji zaprzyjaźnionych



Operator można przeciążyć także posługując się funkcjami nie będącymi
składowymi klasy



W tym celu najczęściej stosuje się funkcje zaprzyjaźnione



Funkcje zaprzyjaźnione nie są składowymi klasy, nie jest więc do nich
przekazywany wskaźnik this



Dlatego do zaprzyjaźnionej funkcji operatora operandy przekazywane są w
sposób jawny



Oznacza to, że funkcja zaprzyjaźniona służąca do przeciążania operatora
dwuargumentowego ma dwa parametry, a funkcja zaprzyjaźniona
przeciążająca operator jednoargumentowego ma jeden parametr



Podczas przeciążania operatora dwuargumentowego za pomocą funkcji
zaprzyjaźnionej lewy operand przekazywany jest jako pierwszy, a prawy –
jako drugi



Przykład

Program 5.5

background image

28

Programowanie obiektowe

Funkcje wirtualne



Polimorfizm jest obsługiwany przez język C++ zarówno na etapie
kompilacji (przeciążanie funkcji i operatorów), jak i na etapie wykonania
(dziedziczenie i funkcje wirtualne)



Funkcja wirtualna to metoda składowa zadeklarowana w klasie bazowej
a zdefiniowana w klasie pochodnej



Aby utworzyć funkcję wirtualną należy jej deklaracje w klasie bazowej
poprzedzić słowem kluczowym virtual



Zasadę, pozwalającą funkcjom wirtualnym realizować polimorfizm
określamy w skrócie jako „jeden interfejs, wiele metod”



W klasie bazowej ma miejsce definicja intejfejsu, każda definicja funkcji
wirtualnej w klasie pochodnej to implementacja funkcji specyficznych dla
danej klasy pochodnej

background image

29

Programowanie obiektowe

Funkcje wirtualne



Funkcję wirtualną można wywoływać w „normalny sposób”, tzn.
wykorzystując nazwę obiektu i operator kropki



Do wskazywania obiektów klas pochodnych można wykorzystać wskaźnik
ich klasy bazowej



Wówczas kompilator C++ decyduje o wyborze wersji funkcji na podstawie
typu obiektu wskazywanego przez ten wskaźnik; wybór odbywa się na
etapie wykonania programu



Oznacza to, że wskazanie różnych obiektów spowoduje wskazanie różnych
wersji funkcji wirtualnej



Przykład

Program 6.1

background image

30

Programowanie obiektowe

Funkcje wirtualne



Atrybut virtual jest dziedziczony



Oznacza to, że bez względu na to, ile razy jest dziedziczona funkcja
wirtualna pozostaje funkcją wirtualną



Przykład

Program 6.2

background image

31

Programowanie obiektowe

Funkcje wirtualne



Funkcje wirtualne są hierarchiczne



Funkcja zadeklarowana w klasie bazowej jako virtual może być
przesłonięta (tj. przedefiniowana) w klasie pochodnej, ale nie musi być tak
zawsze



Jeśli w klasie pochodnej funkcja wirtualna nie zostanie przesłonięta, wtedy
obiekty tej klasy odwołujące się do takiej funkcji wirtualnej będą
wykorzystywały funkcję zdefiniowana w klasie bazowej



Przykład

Program 6.3

background image

32

Programowanie obiektowe

Funkcje wirtualne



Przykład: konwersja litrów na galony i temperatury w stopniach Fahrenheita
na stopnie Celsjusza z wykorzystaniem funkcji wirtualnych

Program 6.4

background image

33

Programowanie obiektowe

Szablony



Szablony są jedną z najbardziej wyrafinowanych i najbardziej efektywnych
cech języka C++



Zostały dodane do specyfikacji języka zaledwie kilka lat temu



Dzięki szablonom możliwe jest tworzenie tzw. ogólnych definicji funkcji
i klas



W ogólnych funkcjach lub klasach typ danych, na których operuje funkcja
lub klasa jest określany jako parametr



W konsekwencji można stworzyć funkcję lub klasę, przystosowaną do pracy
z kilkoma różnymi typami danych, bez konieczności jawnego
redefiniowania specyfikacji dla poszczególnych typów



Funkcja może być zatem w pewnym stopniu inteligentna: może
samodzielnie dobrać zarówno typ argumentów, jak typ wyniku samej
funkcji!

background image

34

Programowanie obiektowe

Szablony funkcji



Funkcję ogólną (szablon funkcji) tworzymy posługując się słowem
kluczowym template

template <class Ttype > typ_zwracany nazwa_funkcji(lista parametrów)

{

// ciało funkcji

}

gdzie:

Ttype – symboliczna nazwa typu danych, wykorzystywanych przez
funkcję (podczas tworzenia konkretnej wersji funkcji kompilator
zamienia ten typ na rzeczywisty typ danych)
class - słowo kluczowe konieczne, aby powstał szablon;

Uwaga:

Jeśli parametrów szablonu jest więcej niż jeden, to po przecinku
powtarzamy dla słowo class i podajemy kolejną nazwę parametru;

background image

35

Programowanie obiektowe



Funkcje ogólne są podobne do funkcji przeciążonych, ale podczas pracy
z nimi obowiązuje więcej ograniczeń



W odróżnieniu od funkcji przeciążonej funkcja ogólna musi we wszystkich
wersjach wykonywać te same operacje (tyle, że na zmiennych różnych
typów)



Nazwa szablonu musi być zdefiniowana w zakresie globalnym, czyli na
zewnątrz wszystkich funkcji i klas.



Parametr szablonu musi wystąpić jako typ argumentu funkcji definiowanej
tym szablonem.



WNIOSEK: nie można wprost zadać szablonem funkcji o typie innym niż
typ jej argumentów; jest to możliwe poprzez specjalne obejście ograniczeń
języka.



Parametrem szablonu funkcji może być typ obiektu czyli nazwa klasy.



Definicja szablonu nie powoduje jeszcze utworzenia funkcji szablonowej.
Zostanie ona utworzona dopiero po wystąpieniu w kodzie nazwy tej
funkcji. Utworzenie odbędzie się zgodnie z „recepturą” zapisaną w
szablonie.

Szablony funkcji

background image

36

Programowanie obiektowe



Nazwa funkcji szablonowej nie powinna pokrywać się z innymi nazwami
zmiennych i funkcji globalnych.



Operacja zapisana w funkcji poddana jest takim samym regułom na
poprawność operacji jak we wszystkich innych funkcjach, czyli nie wykona
się na przykład operacja arytmetyczna na zmiennych znakowych.



Parametr szablonu – nazwany podczas deklarowania szablonu – nie musi
mieć tej samej nazwy podczas definiowania szablonu.



Dwa szablony o takiej samej nazwie mogą wystąpić w tym samym kodzie;
należy tylko uważać, aby jeden nie był szczególnym przypadkiem drugiego
(wówczas linker nie wiedziałby, z którego ma skorzystać)

Szablony funkcji

background image

37

Programowanie obiektowe



Szablon wstawiając do wzorca funkcji różne typy argumentów realizuje tak
naprawdę przeciążenie nazwy funkcji.



Sam szablon też może być przeciążony czyli w tym samym zakresie
ważności może wystąpić dwa lub kilka razy z tą sama nazwą, ale różnymi
parametrami, np.:

template <class typ> void funkcja (typ, int);
template <class typ> void funkcja (typ, int, float, char);

Szablony funkcji

background image

38

Programowanie obiektowe



Szablon jest deklarowany globalnie, ale stosowany lokalnie; dlatego nie
powinien używać nazw zmiennych globalnych



UWAGA: szablony ciągle są nowością: w różnych środowiskach języka
C++, a szczególnie w zakresie pracy linkerów mogą występować problemy



W szablonie możemy stosować kwalifikatory inline, extern, static.
Pamiętajmy jednak, że słowo to odnosi się ostatecznie nie do szablonu ale
do funkcji, która wg tego szablonu zostanie zbudowana:



Przykład

template <class bb> inline bb wieksza (bb z1, bb z2)

{

return (z1>z2)? z1:z2;

}

Szablony funkcji

background image

39

Programowanie obiektowe

Szablony funkcji



Funkcje ogólne (szablony funkcji) są bardzo użyteczne



Można je stosować w tych sytuacjach, kiedy różne funkcje wykorzystują
ten sam ogólny algorytm



Przykład: funkcja ogólna, realizująca sortowanie bąbelkowe

Program 6.7

background image

40

Programowanie obiektowe

Sortowanie przez zamianę (bąbelkowe)

44

Klucze

pocz

ą

tkowe

55

i = 2

42

i = 3

18

i = 5

06

94

i = 4

67

44

12

42

18

06

94

67

06

06

K r o k i a l g o r y t m u

12

55

55

18

94

42

67

44

44

55

42

18

67

94

12

12

06

44

55

42

18

67

94

12

06

44

55

42

18

67

94

12

i = 6

06

44

55

42

18

67

94

12

i = 7

06

44

55

42

18

67

94

12

i = 8

background image

41

Programowanie obiektowe

Szablony klas



Oprócz funkcji ogólnych (szablonów funkcji) w języku C++ można także
definiować szablony klas (klasy ogólne)



W takim przypadku tworzona klasa zawiera definicje wszystkich
wykorzystywanych przez nią algorytmów, jednak typ danych, na których
klasa operuje, zostanie przekazany do niej jako parametr dopiero w chwili
tworzenia obiektów

background image

42

Programowanie obiektowe

Szablony klas



Ogólna składnia szablonu klasy:

template <class Ttype > class nazwa_klasy

{

// ciało klasy

}

gdzie Ttype oznacza nazwę typu, który zostanie określony podczas tworzenia

obiektu (egzemplarza klasy)



Można zdefiniować więcej niż jeden typ ogólny: wówczas kolejne typy są
oddzielane od siebie przecinkami;



Po utworzeniu klasy ogólnej można stworzyć obiekt (egzemplarz klasy),
posługując się składnią:

nazwa_klasy <typ_rzeczywisty> nazwa_obiektu;

background image

43

Programowanie obiektowe

Szablony klas



Przykład 1: szablon klasy: stos ogólny



Przykład 2: szablon klasy z dwoma typami ogólnymi

Program 6.8

Program 6.9

background image

44

Programowanie obiektowe

Szablony klas



Przeciążanie operatora []



Przykład 3: szablon klasy: ogólna, bezpieczna tablica

Program 6.10a

Program 6.10b

Program 6.10

background image

45

Programowanie obiektowe

Szablony klas



W szablonach klas można posługiwać się także argumentami, które nie
służą do określenia typu



Składnia szablonu, w przypadku użycia takiego parametru nie ulega zmianie

Program 6.11

background image

46

Programowanie obiektowe

Szablony klas



W szablonach klas można definiować argumenty domyślne, związane z
typem ogólnym, np.

template <clas X=int> class MojaKlasa( ...



Dopuszcza się także definiowanie wartości domyślnych dla argumentów nie
służących do określania typu



Wartość domyślna jest wykorzystywana wtedy, gdy podczas tworzenia
obiektu (egzemplarza klasy) żadna wartość nie zostanie wyspecyfikowana w
sposób jawny



Wartości domyślne dla argumentów nie służących do określania typu
definiuje się w taki sam sposób, jak dla standardowych argumentów funkcji



Przykład

Program 6.12

background image

47

Programowanie obiektowe


Wyszukiwarka

Podobne podstrony:
PO W1 2 II ZIN id 364239 Nieznany
PO W1 IV ZIN id 364236 Nieznany
PO W3 IV ZIN id 364242 Nieznany
PO W2 IV ZIN id 364240 Nieznany
Po prostu PageMaker 7 id 364216 Nieznany
II Wyklad id 210139 Nieznany
II 83 id 209795 Nieznany
II 31 id 209763 Nieznany
II czesc id 209842 Nieznany
biochemia II 1 plus id 86425 Nieznany (2)
po w9 utf8 id 557617 Nieznany
F II wyklad 4 id 167240 Nieznany
II 32 id 209764 Nieznany
II 43 id 209770 Nieznany
D 2 calosc I,II,III id 130089 Nieznany
po w13 utf8 id 557611 Nieznany
biochemia II 2 plus id 86427 Nieznany (2)

więcej podobnych podstron