kurs języka c++ – wykład 6 (7.04.2014)
DESCRIPTION
Kurs języka C++ – wykład 6 (7.04.2014). Polimorfizm. Spis treści. Metody wirtualne Implementacja polimorfizmu Wczesne i późne wiązanie metod wirtualnych Klasy abstrakcyjne Klasa pair Klasa vector. Składowe funkcje wirtualne. - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/1.jpg)
KURS JĘZYKA C++ – WYKŁAD 6 (7.04.2014)
Polimorfizm
![Page 2: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/2.jpg)
SPIS TREŚCI
Metody wirtualne Implementacja polimorfizmu Wczesne i późne wiązanie metod wirtualnych Klasy abstrakcyjne Klasa pair<> Klasa vector<>
![Page 3: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/3.jpg)
SKŁADOWE FUNKCJE WIRTUALNE
Składowe funkcje wirtualne pozwalają na przedefiniowanie w każdej klasie pochodnej funkcji składowych zadeklarowanych w klasie bazowej.
Poprzez funkcje wirtualne w programie zapewnione jest wywołanie metody najlepiej odpowiadającej obiektowi.
Składowe funkcje wirtualne należy opatrzyć deklaratorem virtual (wewnątrz klasy).
W definicji metody wirtualnej poza klasą nie używa się deklaratora virtual.
![Page 4: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/4.jpg)
SKŁADOWE FUNKCJE WIRTUALNE Przykład deklaracji klas z metodami wirtualnymi i zwykłymi:
class bazowa{public: void opis_zwykly (); virtual void opis_wirtualny ();};
class pochodna: public bazowa{public: void opis_zwykly (); virtual void opis_wirtualny ();};
![Page 5: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/5.jpg)
SKŁADOWE FUNKCJE WIRTUALNE
Przykład definicji metod wirtualnych i zwykłych:
void bazowa::opis_zwykly(){ cout << "bazowa::opis_zwykly()" << endl; }void bazowa::opis_wirtualny(){ cout << "bazowa::opis_wirtualny()" << endl; }
void pochodna::opis_zwykly(){ cout << "pochodna::opis_zwykly()" << endl; }void pochodna::opis_wirtualny(){ cout << "pochodna::opis_wirtualny()" << endl; }
![Page 6: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/6.jpg)
SKŁADOWE FUNKCJE WIRTUALNE
Przykład użycia metod wirtualnych i zwykłych:
bazowa *a = new bazowa();a->opis_zwykly();a->opis_wirtualny();// bazowa::opis_zwykly()// bazowa::opis_wirtualny()
bazowa *b = new pochodna();b->opis_zwykly();b->opis_wirtualny();// bazowa::opis_zwykly()// pochodna::opis_wirtualny()
![Page 7: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/7.jpg)
SKŁADOWE FUNKCJE WIRTUALNE
Funkcja wirtualna musi być zdefiniowana dla klasy, w której po raz pierwszy została zadeklarowana.
Funkcji wirtualnej można używać nawet wtedy, gdy z jej klasy nie wyprowadzi się żadnej klasy pochodnej.
Klasa pochodna, która nie potrzebuje specjalnej wersji funkcji wirtualnej, nie musi jej dostarczać.
Funkcja w klasie pochodnej z tą samą nazwą i z tą samą listą argumentów co funkcja wirtualna w klasie podstawowej nadpisuje (ang. override) wersję funkcji wirtualnej z klasy bazowej.
![Page 8: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/8.jpg)
POLIMORFIZM
Uzyskanie zachowania się funkcji adekwatnego do typu obiektu nazywa się polimorfizmem (ang. polymorphism).
Klasa z funkcjami wirtualnymi nazywa się klasą polimorficzną.
Aby zachowanie obiektu było polimorficzne należy się do niego odnosić za pomocą wskaźnika albo referencji.
Dzięki polimorfizmowi programy stają się rozszerzalne (ang. extensibility) – modyfikacja kodu polega na dodaniu nowej klasy bez potrzeby zmian w kodzie istniejącym.
![Page 9: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/9.jpg)
IMPLEMENTACJA ZACHOWAŃ POLIMORFICZNYCH
Obiekty klas polimorficznych mają dodatkowe pole identyfikujące typ obiektu.
Decyzję o wyborze funkcji do wykonania podejmuje się w trakcie działania programu (jest to tak zwane późne wiązanie, w przeciwieństwie do zwykłych funkcji gdzie obowiązuje wczesne wiązanie).
Każda klasa polimorficzna posiada swoje miejsce w tablicy metod wirtualnych.
Polimorfizm jest więc kosztowny (miejsce i czas) – dlatego nie wszystkie metody są wirtualne.
![Page 10: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/10.jpg)
REZULTAT FUNKCJI WIRTUALNEJ Przy nadpisywaniu funkcji wirtualnej trzeba zachować
odpowiedni typ rezultatu: albo rezultat musi być identyczny, albo rezultat musi być kowariantny (referencja lub wskaźnik
do obiektu tej samej klasy lub do klasy, dla której jest ona jednoznaczną i dostępną klasą podstawową).
Przykład:owoc * bazowa::fun () {/*…*/}pomelo * pochodna::fun () {/*…*/}
![Page 11: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/11.jpg)
INNE CECHY FUNKCJI WIRTUALNYCH
Funkcja wirtualna w klasie nie może być statyczna. Dostęp do funkcji wirtualnej może być zmieniony w
klasach pochodnych (co zależy od sposobu dziedziczenia) – dostęp ten zależy więc tylko od typu wskaźnika albo referencji.
Funkcje wirtualne mogą być przyjacielami w innych klasach.
![Page 12: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/12.jpg)
FUNKCJA WIRTUALNA WCZEŚNIE ZWIĄZANA
Funkcja wirtualna będzie wcześnie związana gdy będzie wywołana na rzecz konkretnego obiektu znanego z nazwy:klasa ob;// …ob.funwirt();
Funkcja wirtualna będzie wcześnie związana gdy użyjemy kwalifikatora zakresu:wsk->klasa::funwirt();ref.klasa::funwirt();
Funkcja wirtualna będzie wcześnie związana gdy wywołamy ją w konstruktorze.
Funkcja wirtualna może być wbudowana.
![Page 13: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/13.jpg)
KLASY ABSTRAKCYJNE
Klasy abstrakcyjne służą do definiowania interfejsów (pojęć abstrakcyjnych).
Klasa abstrakcyjna zawiera co najmniej jedną abstrakcyjną metodą wirtualną (funkcja czysto wirtualna).
Deklaracja metody czysto wirtualnej wygląda następująco:virtual typ funkcja (lista-argumentów) = 0;
Nie trzeba (ale można) podawać definicji metody czysto wirtualnej. W klasach potomnych, które nie mają być klasami abstrakcyjnymi,
należy zdefiniować wszystkie odziedziczone metody abstrakcyjne.
![Page 14: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/14.jpg)
KLASY ABSTRAKCYJNE
Nie wszystkie metody w klasie abstrakcyjnej muszą być abstrakcyjne. Żaden konstruktor ani destruktor nie może być abstrakcyjny. Nie można utworzyć obiektu klasy abstrakcyjnej:
nie wolno zdefiniować funkcji, która odbierałaby argument takiej klasy przez wartość;
nie wolno zdefiniować funkcji, która zwracałaby wynik takiej klasy przez wartość;
klasa abstrakcyjna nie może być typem w jawnej konwersji.
![Page 15: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/15.jpg)
WIRTUALNY DESTRUKTOR
W klasach polimorficznych (zawierających metody wirtualne) destruktor definiujemy jako wirtualny.
![Page 16: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/16.jpg)
KONSTRUKTOR NIE MOŻE BYĆ WIRTUALNY ALE…
Czasami istnieje potrzeba wyprodukowania nowego obiektu tej samej klasy – w takiej sytuacji można zdefiniować funkcję wirtualną, która będzie przygotowywać taki obiekt (zastąpi konstruktor domyślny albo kopiujący).
![Page 17: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/17.jpg)
KLASA PAIR<>
W pliku nagłówkowym <utility> zdefiniowano szablon klasy pair<F,S>, który służy do przechowywania pary wartości.
Para std::pair<> to struktura z dwoma polami first i second dowolnych typów podawanych jako parametry wzorca.
Przykład:pair<string,double> pi = new pair<string,double>(”pi”,3.141593);
W szablonie klasy std::pair<> zdefiniowano oprócz konstruktora z dwiema wartościami inicjalizującymi pola first i second także konstruktor kopiujący i domyślny.
![Page 18: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/18.jpg)
KLASA PAIR<>
Typy występujące w parze mogą być wydedukowane, gdy para jest tworzona za pomocą funkcji szablonowej make_pair().
Przykład:pair<string,double> e = make_pair(string(”e”),2.718282);
Dla szablonu klasy std::pair<> zdefiniowano nieskładowe operatory relacji porównujących == i < (porównywane są pierwsze pola, a gdy te są równe porównywane są drugie pola).
Funkcja składowa oraz zewnętrzna funkcja szablonowa swap<>() zamienia zawartości dwóch par.
![Page 19: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/19.jpg)
KLASA VECTOR<> W pliku nagłówkowym <vector> zdefiniowano szablon klasy vector<T>, który służy do przechowywania dowolnej liczby wartości określonego typu.
Kolekcja std::vector<> przechowuje swoje elementy w tablicy dynamicznej – dodawanie (metoda push_back()) i usuwanie (metoda pop_back()) elementów na końcu tablicy działa bardzo szybko.
Przykład:vector<int> coll;for (int i=1; i<=10; ++i) coll.push_back(i*i);for (int i=0; i<coll.size(); ++i) cout << coll[i] << ’ ’;cout << endl;
![Page 20: Kurs języka C++ – wykład 6 (7.04.2014)](https://reader035.vdocuments.site/reader035/viewer/2022062315/56814f84550346895dbd39e0/html5/thumbnails/20.jpg)
KLASA VECTOR<> W kolekcji std::vector<> istnieją metody do wstawiania
elementu na początku wektora push_front() i usuwania elementu z początku pop_front().
Dostęp do elementów w wektorze jest realizowany za pomocą operatora indeksowania [] albo za pomocą metody at(); odczytanie wartości pierwszego elementu w wektorze można zrobić za pomocą metody front() a ostatniego za pomocą back().
Metoda empty() mówi czy wektor jest pusty a metoda size() zwraca liczbę wszystkich elementów w wektorze.
Metoda clear() usuwa wszystkie elementy z wektora.