K URS JĘZYKA C++ – WYKŁAD 6 (7.04.2014) Polimorfizm.

Slides:



Advertisements
Podobne prezentacje
C++ wykład 2 ( ) Klasy i obiekty.
Advertisements

Programowanie obiektowe
Klasy abstrakcyjne i interfejsy
Programowanie obiektowe PO PO - LAB 2 Wojciech Pieprzyca.
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Programowanie obiektowe
Programowanie obiektowe
Programowanie obiektowe
Programowanie obiektowe PO PO - LAB 3 Wojciech Pieprzyca.
Metody wirtualne.
Wzorce.
Static, const, volatile.
Dziedziczenie. Po co nam dziedziczenie? class osoba { char * imie, char * imie, * nazwisko; * nazwisko;public: void wypisz_imie(); void wypisz_imie();
Programowanie w środowisku sieciowym
Sposoby implementacji asocjacji
Programowanie obiektowe w Javie
OOPC++ - dziedziczenie1 Uwagi VS2003 Wykłady (nie na rainbow!)
OOPC++ - wstêp, klasy1 Klasy Do struktury można dołączyć operacje działające na jej polach. struct date { int day, month, year; void set (int d, int m,
DZIEDZICZENIE · klasy bazowe i klasy pochodne WyświetlAutora( ) Autor
Obiektowe metody projektowania systemów
C++ wykład 5 ( ) Dziedziczenie.
C++ wykład 6 ( ) Polimorfizm.
C++ wykład 2 ( ) Klasy i obiekty.
Zasady zaliczenia Warunki uzyskania zaliczenia:
Projektowanie i programowanie obiektowe II - Wykład II
Programowanie obiektowe III rok EiT
Podstawy programowania
Podstawy programowania II
T: Różnice pomiędzy programowaniem strukturalnym a obiektowym
C# cz.3 Obiektowość w C# Krzysztof Fediuk
Programowanie obiektowe III rok EiT
Jerzy F. Kotowski1 Informatyka I Wykład 14 DEKLARATORY.
Programowanie obiektowe III rok EiT dr inż. Jerzy Kotowski Wykład XIII.
Programowanie obiektowe III rok EiT dr inż. Jerzy Kotowski Wykład IX.
WPROWADZENIE W ŚWIAT OBIEKTÓW
Java – coś na temat Klas Piotr Rosik
INTERFEJSY I KLASY WEWNĘTRZNE
Programowanie obiektowe
Programowanie obiektowe Wykład 6 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Dariusz Wardowski.
Programowanie obiektowe 2013/2014
Kurs języka C++ – wykład 3 ( )
Kurs języka C++ – wykład 8 ( )
Kurs języka C++ – wykład 9 ( )
Programowanie w języku C++
Kurs języka C++ – wykład 5 ( )
K URS JĘZYKA C++ – WYKŁAD 7 ( ) Wyjątki.
K URS JĘZYKA C++ – WYKŁAD 10 ( ) Szablony.
Programowanie strukturalne i obiektowe C++
Programowanie strukturalne i obiektowe C++ Przeładowanie operatorów Robert Nowak.
Kurs języka C++ – wykład 4 ( )
K URS JĘZYKA C++ – WYKŁAD 1 ( ) Łagodne wprowadzenie do języka C++
K URS JĘZYKA C++ – WYKŁAD 2 ( ) Klasy i obiekty.
Klasy ( uzupełnienie ). Definicja klasy Klasa jest zbiorem logicznie powiązanych danych i funkcji, przeznaczonych do realizacji konkretnego zadania; Zamknięcie.
Design Patterns.: Visitor :.. Plan prezentacji 1. Trochę statystyk. 2. Zadanie problemowe. 3. Rozwiązanie… Visitor. 4. Visitor w UML (a,b,c). 5. Implementacja.
Obiektowe metody projektowania systemów Adapter. Wstęp: „Dostosowanie interfejsu klasy do interfejsu, którego oczekuje użytkownik. Adapter umożliwia współprace.
Dziedziczenie wielobazowe. dana klasa może mieć kilka bezpośrednich klas bazowych: dana klasa może mieć kilka bezpośrednich klas bazowych: kolorpołożenie.
Programowanie Zaawansowane
Dziedziczenie Wykład 7 Dziedziczenie sekwencyjne
Wykład 8 Polimorfizm 1.Funkcje polimorficzne 2.Czyste funkcje wirtualne i klasy abstrakcyjne PO8-1 / 38.
Podstawy informatyki Funkcje Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
K URS JĘZYKA C++ – WYKŁAD 7 ( ) Konwersje.
Dziedziczenie, polimorfizm, Interfejsy
Programowanie Obiektowe – Wykład 6
Kurs języka C++ – wykład 3 ( )
Kurs języka C++ – wykład 6 ( )
Programowanie Obiektowe – Wykład 2
Programowanie obiektowe
PGO Dziedziczenie Michail Mokkas.
Zapis prezentacji:

K URS JĘZYKA C++ – WYKŁAD 6 ( ) Polimorfizm

S PIS TREŚCI Metody wirtualne Implementacja polimorfizmu Wczesne i późne wiązanie metod wirtualnych Klasy abstrakcyjne Klasa pair<> Klasa vector<>

S KŁ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.

S KŁ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 (); };

S KŁ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; }

S KŁ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()

S KŁ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.

P OLIMORFIZM 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.

I MPLEMENTACJA 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.

R EZULTAT 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 () {/*…*/}

I NNE 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.

F UNKCJA 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.

K LASY 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.

K LASY 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.

W IRTUALNY DESTRUKTOR W klasach polimorficznych (zawierających metody wirtualne) destruktor definiujemy jako wirtualny.

K ONSTRUKTOR 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).

K LASA PAIR <> W pliku nagłówkowym zdefiniowano szablon klasy pair, 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 pi = new pair (”pi”, ); 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.

K LASA PAIR <> Typy występujące w parze mogą być wydedukowane, gdy para jest tworzona za pomocą funkcji szablonowej make_pair(). Przykład: pair e = make_pair(string(”e”), ); 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.

K LASA VECTOR <> W pliku nagłówkowym zdefiniowano szablon klasy vector, 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 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;

K LASA 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.