Programowanie obiektowe w języku C++

Wielkość: px
Rozpocząć pokaz od strony:

Download "Programowanie obiektowe w języku C++"

Transkrypt

1 Programowanie obiektowe w języku C++ Roman Simiński roman.siminski@us.edu.pl Funkcje wirtualne Wskaźniki do obiektów Polimorfizm

2 Wczesne i późne wiązanie Funkcje wirtualne 2

3 Rozpoczynamy od przykładu Runner raz jeszcze class Runner Jedna z kilku omawianych wersji klasy Runner public: Runner( int startx = 1, int starty = 1, char startshape = '*' ); void setx( int newx ); void sety( int newy ); void setshape( char newshape ); int getx(); int gety(); char getshape(); void show(); void hide(); void moveup(); void movedown(); void moveleft(); void moveright(); private: int x, y; char shape; bool isxonscreen( int x ); bool isyonscreen( int y ); ; 3

4 Implementacje wybranych funkcji klasy Runner void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); void Runner::moveDown() hide(); if( y < 24 ) ++y; show(); 4

5 Problem chcemy aby Runner zostawiał swój ślad Chcemy aby ruchomy punkt ekranowy pozostawiał ślad. Dotychczasowa implementacja klasy Runner wymazuje znak na pozycji poprzedniej przed umieszczeniem znaku na nowej pozycji. Zobaczmy jak to wygląda w kodzie klasy Runner. 5

6 Dlaczego Runner nie zostawia śladu? void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); void Runner::moveDown() hide(); if( y < 24 ) ++y; show(); 6

7 Dlaczego Runner nie zostawia śladu? void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); void Runner::moveDown() hide(); if( y < 24 ) ++y; show(); Aby Runner zostawiał ślad wystarczy przerobić jego funkcję hide(), tak aby nie wymazywała znaku na pozycji poprzedniej.... 7

8 Dlaczego Runner nie zostawia śladu? void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); void Runner::moveDown() hide(); if( y < 24 ) ++y; show(); Nie przerabiamy klasy! Klasę Runner zostawiamy w spokoju. Ona jest dobra i niech sobie taka jest. Jeżeli zachowanie obiektu pewnej klasy nam nie odpowiada, staramy się stworzyć nową klasę wykorzystując dziedziczenie a następnie zmienić zachowanie obiektu nowej klasy poprzez redefinicję nieodpowiadających nam funkcji składowych. 8

9 Obiektowe podejście do zmian zachowania obiektu class Runner redefinicja public: Runner( int startx = 1, int starty = 1, char startshape = '*' ); void setx( int newx ); void sety( int newy ); void setshape( char newshape ); int getx(); int gety(); char getshape(); void show(); void hide(); void moveup(); void movedown(); void moveleft(); void moveright(); private: int x, y; char shape; bool isxonscreen( int x ); bool isyonscreen( int y ); ; class RunnerWithTrace : public Runner public: RunnerWithTrace( int startx = 1, int starty = 1, char startshape = '*' ); ; void hide(); Runner zostawiający ślad to dobry kandydat na nową klasę niech ona nazywa się RunnerWithTrace. Tworzymy ją wykorzystując dziedziczenie. W klasie RunnerWithTrace dokonujemy redefinicji funkcji składowej hide(). Spodziewamy się, że obiekt klasy pochodnej będzie reagował po swojemu na komunikat hide. 9

10 Dwie implementacje funkcji hide() void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); void RunnerWithTrace::hide() // Nic, dosłownie nic! Implementacja funkcji hide() klasy Runner Klasa RunnerWithTrace inaczej reaguje na komunikat hide posiada własną wersję funkcji reagującej na ten komunikat. W innych przypadkach obiekty klasy RunnerWithTrace będą zachowywały się tak samo jak obiekty klasy Runner, dziedziczą przecież pozostałe składowe tej klasy. Implementacja funkcji hide() klasy RunnerWithTrace 10

11 Wywołanie funkcji show() oraz hide() dla obiektu klasy Runner void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); Sprawdźmy, jak to wszystko działa dla obiektu klasy Runner. Zgodnie z oczekiwaniami wszystko działa jak poprzednio wprowadzenie klasy RunnerWithTrace niczego nie zmienia. void RunnerWithTrace::hide() // Nic, dosłownie nic! Runner runner( 40, 12, '*' ); runner.show(); runner.hide(); 11

12 Wywołanie funkcji show() oraz hide() dla obiektu klasy RunnerWithTrace void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); Sprawdźmy, jak to wszystko działa dla obiektu klasy RunnerWithTrace. Zgodnie z oczekiwaniami obiekt klasy RunnerWithTrace reaguje po swojemu na komunikat hide. Reakcja polega na wywołaniu funkcji właściwej dla klasy obiektu, do którego został przesłany komunikat. void RunnerWithTrace::hide() // Nic, dosłownie nic! RunnerWithTrace runner( 40, 12, '*' ); runner.show(); runner.hide(); 12

13 Funkcja moveup() dla obiektu klasy Runner void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); void RunnerWithTrace::hide() // Nic, dosłownie nic! Poprzednio wywoływaliśmy funkcję hide() bezpośrednio, zobaczmy jak będzie w przypadku wywołania pośredniego np. via funkcja moveup(). Sprawdźmy, jak to działa dla obiektu klasy Runner. Podobnie jak poprzednio, wszystko działa bez zmian. Runner runner( 40, 12, '*' ); runner.moveup(); 13

14 Funkcja moveup() dla obiektu klasy RunnerWithTrace void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() wywołanie wersji przedefiniowanej hide(); if( y > 1 ) --y; show(); void RunnerWithTrace::hide() // Nic, dosłownie nic! RunnerWithTrace runner( 40, 12, '*' ); runner.moveup(); Sprawdzamy wywołanie pośrednie funkcji hide() via funkcja moveup() tym razem dla obiektu klasy RunnerWithTrace. Oczekujemy, że dla obiektu klasy RunnerWithTrace wywołana zostanie jego własna wersja funkcji hide() a nie wersja klasy bazowej Runner. Kompilujemy, uruchamiamy i... nic. Obiekt klasy RunnerWithTrace nie pozostawia śladu, zachowuje się tak, jakby był obiektem klasy Runner. Dlaczego? 14

15 Klasyczna kompilacja wywołania funkcji Kompilacja void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); void RunnerWithTrace::hide() // Nic, dosłownie nic! Kompilując funkcję moveup() klasy Runner, kompilator jeszcze nic nie wie o dziedziczeniu i generuje kod maszynowy, wywołujący funkcję hide() klasy Runner. Klasa RunnerWithTrace dziedziczy tak skompilowany kod funkcji moveup(), który wywołuje zawsze funkcję hide() klasy Runner. Takie opracowanie wywołania funkcji występowało od zawsze w kompilowanych językach programowania wysokiego poziomu. 15

16 Klasyczna kompilacja wywołania funkcji Kompilacja void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); Chciejstwo: void Runner::moveUp() hide(); if( y > 1 ) --y; show(); została wywołana? void RunnerWithTrace::hide() // Nic, dosłownie nic! Kompilując funkcję moveup() klasy Runner, kompilator jeszcze nic nie wie o dziedziczeniu i generuje kod maszynowy, wywołujący funkcję hide() klasy Runner. Chciejstwo: Czy istnieje możliwość takiego skompilowania Klasa funkcji RunnerWithTrace dziedziczy moveup() klasy Runner, aby wywoływała ona tak odpowiednią skompilowany kod funkcji funkcję hide() w zależności od tego, dla jakiego moveup(), obiektu który wywołuje zawsze została wywołana? funkcję hide() klasy Runner. Chcemy zatem wariantowości: Takie opracowanie wywołania funkcji gdy funkcja moveup() wywoływana jest dla obiektu występowało klasy Runner, od niech zawsze wywołuje on funkcję hide() klasy Runner; w kompilowanych językach gdy funkcja moveup() wywoływana jest dla wysokiego obiektu klasy poziomu. RunnerWithTrace, niech wywołuje ona funkcję hide() klasy RunnerWithTrace. 16

17 Klasyczne wywołanie funkcji nie daje rady Kompilacja void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); void RunnerWithTrace::hide() // Nic, dosłownie nic! Skąd kompilator ma wiedzieć, że czasem chcemy wywołać wersję funkcji hide() klasy RunnerWithTrace? W przypadku klasycznego wywołania kompilator musi podjąć jednoznaczną decyzję, która funkcję wywołać. Ta decyzja zapisywane jest w kodzie maszynowym. Ponieważ kompiluje kod klasy Runner, do kodu maszynowego trafi wywołanie funkcji hide() tej właśnie klasy. Kompilując kod funkcji moveup() kompilator nie wie, dla jakiego obiektu będzie kiedyś wywoływana, nie potrafi spełnić naszego oczekiwania wariantowości. 17

18 Rodzaje wiązania: wywołanie konkretna funkcja Przypisanie konkretnej funkcji do wywołania nazywa się wiązaniem (ang. binding). W języku C++ występują dwa rodzaje wiązania: Wczesne wiązanie (ang. early binding) polega na przypisaniu każdemu wywołaniu funkcji jednoznacznie określonej, konkretnej funkcji już na etapie kompilacji programu. Inna nazwa wiązanie statyczne (ang. static binding). Późne wiązanie (ang. late binding) polega na przypisaniu każdemu wywołaniu funkcji jednoznacznie określonej, konkretnej funkcji dopiero na etapie wykonania programu, w zależności od typu obiektu, którego wywołanie dotyczy. Inna nazwa dynamiczne wiązanie (ang. dynamic binding). Wczesne wiązanie jest charakterystyczne dla języków kompilowanych, realizacja późnego wiązania wymaga od kompilatora stosowania złożonych mechanizmów. Późne wiązanie jest charakterystyczne dla języków interpretowanych, realizacja późnego wiązania jest zwykle dla interpretera łatwa. 18

19 Wiązanie statyczne i dynamiczne Wczesne wiązanie jest od lat stosowne we większości języków kompilowanych, występuje np. w językach Pascal czy C, w których późne wiązanie oficjalnie nie występuje. We większości nowoczesnych, obiektowych języków programowania, występuje możliwość wyboru sposobu wiązania realizowane jest to poprzez różne słowa kluczowe (virtual, override, final, overridable, overrides ). Domyślny sposób wiązania zależy od języka, np. C++ i C# domyślnie wiązanie wczesne a Java, Ruby, Python domyślnie wiązanie późne. Uwaga na temat późnego wiązania pojawia się wiele niespójnych informacji. Może ono być realizowane na wiele sposobów, w zależności od języka programowania, trybu translacji i wsparcia ze strony biblioteki czasu wykonania. Niezależnie od przyjętej koncepcji realizacji, późne wiązanie jest zwykle wolniejsze od wczesnego konieczne jest bowiem ustalenie w czasie działania programu, która wersja funkcji ma być wywołana. 19

20 Późne wiązania pozwoli rozwiązać problem wywołania funkcji hide() Kompilacja void Runner::hide() con.writecharxy( x, y, ' ' ); void Runner::moveUp() hide(); if( y > 1 ) --y; show(); void RunnerWithTrace::hide() // Nic, dosłownie nic! Runner runner( 40, 12, '*' ); runner.moveup(); RunnerWithTrace runner( 40, 12, '*' ); runner.moveup(); Jeżeli funkcja hide() będzie wywoływana na zasadzie późnego wiązania to: dla obiektów klasy Runner wywołana zostanie wersja hide() klasy Runner a dla obiektów klasy RunnerWithTrace wywołana zostanie wersja hide() klasy RunnerWithTrace. 20

21 W jaki sposób uzyskać dynamiczne wiązanie w C++? class Runner public: Runner( int startx = 1, int starty = 1, char startshape = '*' ); void setx( int newx ); void sety( int newy ); void setshape( char newshape ); int getx(); int gety(); char getshape(); void show(); virtual void hide(); void moveup(); void movedown(); void moveleft(); void moveright(); private: int x, y; char shape; bool isxonscreen( int x ); bool isyonscreen( int y ); ; Dynamiczne wiązanie w języku C++ uzyskuje poprzez wykorzystanie funkcji wirtualnych. Słowo kluczowe virtual w deklaracji funkcji oznacza, że każde wywołanie tej funkcji ma odbywać się na zasadzie późnego wiązania. Wprowadzenie tej jednej modyfikacji spowoduje, że klasa RunnerWithTrace zacznie działać zgodnie z oczekiwaniami. Słowo virtual występuje w deklaracji (prototypie) funkcji. To jest funkcja wirtualna, kompilator C++ wygeneruje kod w taki sposób, aby konkretna wersja wywoływanej funkcji została ustalona w trakcie wykonania programu. 21

22 Funkcje wirtualne są wiązane dynamicznie class Runner public: virtual void hide(); ; class RunnerWithTrace : public Runner public: void hide(); ; void Runner::hide() con.writecharxy( x, y, ' ' ); Od tego momentu funkcja hide() jest funkcją wirtualną, podlegającą późnemu wiązaniu. Redefinicja funkcji hide() w dowolnej klasie pochodnej jest również funkcją wirtualną, niezależnie czy słowo virtual wystąpi, czy nie. W definicjach funkcji umieszczanych poza ciałem klasy słowa virtual się nie używa. void RunnerWithTrace::hide() // Nic, dosłownie nic! 22

23 Jak działa dynamiczne wiązanie w C++? Dynamiczne wiązanie jest łatwe w realizacji dla języków interpretowanych, interpreter tłumaczy kolejne fragmenty kodu i nadzoruje ich wykonanie. Kompilator tłumaczy kod przed wykonaniem programu, musi zatem tak wygenerować kod wywołań funkcji wirtualnych, aby w trakcie wykonania programu wszystko odbyło się automatycznie. W języku C++ osiąga się to poprzez tablicę funkcji wirtualnych. Tablica funkcji wirtualnych zawiera adresy funkcji wirtualnych danej klasy, dla każdej klasy występuje jedna taka tablica, wspólna dla wszystkich obiektów takiej klasy. Każdy obiekt posiada ukryte pole, będące wskaźnikiem na tablicę funkcji wirtualnych swojej klasy. Wskaźnik tablicy funkcji wirtualnych (ang. virtual table pointer vptr, vpointer, vtp) jest zwykle albo pierwszym albo ostatnim polem klasy. 23

24 Jak działa dynamiczne wiązanie w C++? Załóżmy, że funkcja show() klasy Runner jest również wirtualna i nie została ponownie zdefiniowana w klasie RunnerWithTrace: class Runner public: virtual void show(); virtual void hide(); ; void moveup(); void movedown(); void moveleft(); void moveright(); class RunnerWithTrace : public Runner public: void hide(); ; // Kilka obiektów obu klas Runner r1( 1, 1, '*' ), r2( 10, 10, '#'); RunnerWithTrace r3( 20, 20, '%' ), r4( 5, 5, '$' ); 24

25 Tablice funkcji wirtualnych dla klas Runner i RunnerWithTrace r1 : Runner x 1 y 1 shape * vptr r2 : Runner x 10 y 10 shape # vptr r3 : RunnerWithTrace x 20 y 20 shape % vptr r4 : RunnerWithTrace x 5 y 5 shape $ vptr Tablica funkcji wirtualnych klasy Runner Tablica funkcji wirtualnych klasy RunnerWithTrace void Runner::show() con.writecharxy( x, y, shape ); void Runner::hide() con.writecharxy( x, y, ' ' ); Funkcje wirtualne void RunnerWithTrace::hide() // Nic, dosłownie nic! Jakie funkcje zostaną wywołane? r1.show(); r1.hide(); r1.moveup(); r3.show(); r3.hide(); r3.moveup(); 25

26 Kilka uwag na temat funkcji wirtualnych i tablicy funkcji wirtualnych Oczywiście funkcje niewirtualne są wywoływane statycznie i nie występują w tablicy funkcji wirtualnych. Ustalenie konkretnej wersji funkcji wirtualnej odbywa się w czasie działania programu, na podstawie zawartości tablicy funkcji wirtualnych. Wywołanie funkcji wirtualnych odbywa się w dwóch krokach: odnalezienie adresu funkcji w tablicy funkcji wirtualnych obiektu, którego wywołanie dotyczy; wywołanie odpowiedniej funkcji wg odnalezionego adresu. Uwaga proszę zapamiętać, że wywołanie funkcji wirtualnej odbywa się z wykorzystaniem tablicy obiektu, którego wywołanie dotyczy. Tablica metod wirtualnych inicjowana jest przez konstruktor obiektu, który zawiera ukryty kod wypełniający tablicę adresami funkcji odpowiednich dla konstruowanego obiektu. 26

27 Efektywność wywołania funkcji wirtualnych Wywołanie funkcji wirtualnej musi być wolniejsze od wywołania zwykłej funkcji. Dla zwykłej funkcji wykonywany jest natychmiastowy skok do podprogramu, którego adres jest jednoznacznie określony. Dla funkcji wirtualnej taki skok poprzedzony jest odnalezieniem adresu podprogramu, pod jaki ten skok ma być wykonany. W przypadku fragmentów kodu kluczowych dla efektywności czasowej programu warto dobrze zastanowić się nad wykorzystaniem funkcji wirtualnych cz są one rzeczywiście potrzebne? Interesująca rozmowa na temat efektywności funkcji wirtualnych (w roli glównej Anders Hejlsberg, twórca języka C#, wortal Artima Developer): 27

28 O funkcjach wirtualnych nieco filozoficznie Redefinicja funkcji niewirtualnej: class Runner public: void hide(); void moveup(); ; Redefinicja funkcji niewirtualnej odnosi się tylko do bezpośrednich wywołań w klasie pochodnej, nie wpływa na inne funkcje odziedziczone z klasy bazowej. class RunnerWithTrace : public Runner public: Bezpośrednie wywołanie, działa wersja funkcji hide() void hide(); klasy ; RunnerWithTrace redefinicja udana. RunnerWithTrace r; r.hide(); Pośrednie wywołanie funkcji hide(), zadziała wersja klasy Runner redefinicja nie działa. r.moveup(); 28

29 O funkcjach wirtualnych nieco filozoficznie Redefinicja funkcji wirtualnej: class Runner public: virtual void hide(); void moveup(); ; Redefinicja funkcji wirtualnej odnosi się do bezpośrednich i pośrednich wywołań funkcji, wpływa zatem na inne funkcje odziedziczone z klasy bazowej. class RunnerWithTrace : public Runner public: Bezpośrednie wywołanie, działa wersja funkcji hide() void hide(); klasy ; RunnerWithTrace redefinicja udana. RunnerWithTrace r; r.hide(); Pośrednie wywołanie funkcji hide(), zadziała wersja klasy RunnerWithTrace redefinicja udana. r.moveup(); 29

30 O funkcjach wirtualnych nieco filozoficznie Dziedziczenie przejmuje cały materiał genetyczny klasy bazowej. Bardzo często kod źródłowy klasy bazowej nie jest dostępny dziedziczymy funkcje w postaci skompilowanego kodu maszynowego. Mechanizm funkcji wirtualnych pozwala na zmuszenie odziedziczonego, być może skompilowanego kodu klasy bazowej, do wywołania naszej funkcji. class FramedWindow public: virtual void drawframe() // Rysowanie cienkiej ramki void drawwindow() drawframe(); ; FramedWindow w; w.drawwindow(); class MyFramedWindow : public FramedWindow public: void drawframe() // Rysowanie grubej ramki ; MyFramedWindow w; w.drawwindow(); 30

31 O funkcjach wirtualnych nieco filozoficznie Programista deklarując funkcję jako wirtualną składa obietnicę : Jeżeli działanie mojej funkcji wirtualnej Ci nie odpowiada, utwórz klasę pochodną i zdefiniują własną wersję tej funkcji. Inne funkcje odziedziczone z klasy bazowej, będą używały Twojej wersji. Ta obietnica stanowi podstawę działania wielu obiektowych bibliotek obsługi interfejsu użytkownika, grafiki, połączeń sieciowych, obsługi baz danych. Redefinicja funkcji wirtualnych wymaga uwagi i myślenia niewłaściwa redefinicja może spowodować błędne działanie kodu odziedziczonego po klasie bazowej. Zrozumienie koncepcji, zasady działania oraz metod wykorzystania funkcji wirtualnych jest warunkiem wymaganym i koniecznym dla profesjonalnego programowania obiektowego. 31

32 Wskaźniki do obiektów a hierarchia klas Konwersja wskaźników 32

33 Przypomnienie dostęp do obiektów via zmienne wskaźnikowe Dostęp do obiektu R poprzez wskaźnik runner: Runner R; Runner * runner; runner = &R; runner->show(); runner->moveup(); Dostęp do anonimowego obiektu utworzonego dynamicznie: Runner * runner; runner = new Runner; runner->show(); runner->moveup(); delete runner; Dwa style zapisu odwołań do składowych obiektu via zmienna wskaźnikowa: ( *runner ).setx( 10 ); ( *runner ).sety( 10 ); ( *runner ).setshape( '*' ); ( *runner ).show( ); runner->setx( 10 ); runner->sety( 10 ); runner->setshape( '*' ); runner->show( ); 33

34 Zmienne wskaźnikowe a klasy powiązane dziedziczeniem Runner R; RunnerWithTrace RT; Runner * runner; runner = &R; runner->show(); runner = &RT; runner->show(); runner = new Runner; runner->show(); delete runner; runner = new RunnerWithTrace; runner->show(); delete runner; Ustawienie wskaźnika na obiekt klasy zgodnej z klasą wskaźnika Ustawienie wskaźnika na obiekt klasy pochodnej względem klasy wskaźnika W języku C++ wolno do wskaźnika klasy bazowej przypisać wskazanie obiektu klasy pochodnej, w literaturze anglojęzycznej to upcast (upcasting). Obiekt klasy pochodnej jest przecież pewnego rodzaju obiektem klasy bazowej, dlatego takie przypisanie jest legalne. 34

35 Upcasting, czyli w dziecko staje się rodzicem class Silnik public: int pojemnosc; int lbcylindrow; int moc; ; Upcasting występuje wtedy, gdy do wskaźnika lub referencji klasy bazowej, przypisujemy odwołanie do obiektu klasy pochodnej. Z obiektem klasy pochodnej możemy robić wszystko to, co z obiektem klasy bazowej (relacja is-a). class SilnikTurbo : public Silnik public: float cisnieniedoladowania; ; Silnik * s; s = new SilnikTurbo; s->pojemnosc = 2400; s->moc = 163; s->lbcylindrow = 5; Upcasting nie wymaga żadnych dodatkowych operacji, jest legalny i bezpieczny. cout << endl << s->pojemnosc; cout << endl << s->moc; cout << endl << s->lbcylindrow; 35

36 Upcasting działa ze wskaźnikami i referencjami Silnik * s; s = new SilnikTurbo; s->pojemnosc = 2400; s->moc = 163; s->lbcylindrow = 5; Upcasting via wskaźnik i referencja, obiekt anonimowy tworzony dynamicznie Silnik & sr = * s; sr.pojemnosc = 2400; sr.moc = 163; sr.lbcylindrow = 5; SilnikTurbo silt; Silnik * s = &silt; s->pojemnosc = 2400; s->moc = 163; s->lbcylindrow = 5; Upcasting via wskaźnik i referencja do zwykłego obiektu Silnik & sr = silt; sr.pojemnosc = 3200; sr.moc = 240; sr.lbcylindrow = 8; 36

37 Upcasting oznacza chwilowe ograniczenie dostępności pól pochodnych class Silnik public: int pojemnosc; int lbcylindrow; int moc; ; Utworzony obiekt jest reprezentantem klasy pochodnej SilnikTurbo, jednak lokalizujący go wskaźnik związany jest z klasą bazową Silnik. Doszło do upcastingu dla kompilatora wskazywany obiekt jest teraz obiektem klasy Silnik. class SilnikTurbo : public Silnik public: float cisnieniedoladowania; ; Ponieważ wskaźnik jest związany z klasą Silnik, a w niej Silnik * s; nie ma pola cisnieniedoladowania, odwołania to są s = new SilnikTurbo; nieprawidłowe mimo że tak naprawdę wskazywany s->pojemnosc = 2400; obiekt jest klasy SilnikTurbo. s->moc = 163; s->lbcylindrow = 5; s->cisnieniedoladowania = 0.9; cout << endl << s->pojemnosc; cout << endl << s->moc; cout << endl << s->lbcylindrow; cout << endl << s->cisnieniedoladowania; 37

38 Upcasting czasem oznacza ograniczenie dostępności pól Dostęp do obiektu poprzez wskaźnik jego klasy SilnikTurbo SilnikTurbo * s; s = new SilnikTurbo; s->pojemnosc = 2400; s->moc = 163; s->lbcylindrow = 5; s->cisnieniedoladowania = 0.9; Pełny dostęp do własnych pól oraz pól odziedziczonych. Silnik pojemnosc lbcylindrow moc cisnieniedoladowania Dostęp do obiektu poprzez wskaźnik jego klasy bazowej upcasting SilnikTurbo Silnik * s; s = new SilnikTurbo; s->pojemnosc = 2400; s->moc = 163; s->lbcylindrow = 5; s->cisnieniedoladowania = 0.9; Dostępne tylko pola odziedziczone, czyli jak w klasie bazowej. Silnik pojemnosc lbcylindrow moc cisnieniedoladowania 38

39 Dlaczego upcasting jest potrzebny? Bo jest wygodny! I daje możliwości! void zerujbazowedanesilnika( Silnik * s ) s->pojemnosc = 0; s->moc = 0; s->lbcylindrow = 0; void pokazbazowedanesilnika( Silnik * s ) cout << endl << s->pojemnosc; cout << endl << s->moc; cout << endl << s->lbcylindrow; Silnik sil; SilnikTurbo silt; SilnikHybryda silh; zerujbazowedanesilnika( &sil ); zerujbazowedanesilnika( &silt ); zerujbazowedanesilnika( &silh ); silt.cisnieniedoladowania = 0; silh.mocelektryczna = 0; pokazbazowedanesilnika( &sil ); pokazbazowedanesilnika( &silt ); pokazbazowedanesilnika( &silh ); class Silnik public: int pojemnosc; int lbcylindrow; int moc; ; class SilnikTurbo : public Silnik public: float cisnieniedoladowania; ; class SilnikHybryda : public Silnik public: int mocelektryczna; ; 39

40 Upcasting działa również z referencjami void zerujbazowedanesilnika( Silnik & s ) s.pojemnosc = 0; s.moc = 0; s.lbcylindrow = 0; void pokazbazowedanesilnika( Silnik & s ) cout << endl << s.pojemnosc; cout << endl << s.moc; cout << endl << s.lbcylindrow; Silnik sil; SilnikTurbo silt; SilnikHybryda silh; zerujbazowedanesilnika( sil ); zerujbazowedanesilnika( silt ); zerujbazowedanesilnika( silh ); silt.cisnieniedoladowania = 0; silh.mocelektryczna = 0; pokazbazowedanesilnika( sil ); pokazbazowedanesilnika( silt ); pokazbazowedanesilnika( silh ); class Silnik public: int pojemnosc; int lbcylindrow; int moc; ; class SilnikTurbo : public Silnik public: float cisnieniedoladowania; ; class SilnikHybryda : public Silnik public: int mocelektryczna; ; 40

41 Czy jest downcasting? Tak, ale on może być przyczyną klopotów... SilnikTurbo silt; s.pojemnosc = 2400; s.moc = 163; s.lbcylindrow = 5; s.cisnieniedoladowania = 0.9; Upcasting: Silnik * s; s = &silt; s->cisnieniedoladowania = 0.5; s silt : SilnikTurbo pojemnosc 2400 lbcylindrow 5 moc 163 cisnieniedoladowania 0.9 pojemnosc 2400 lbcylindrow 5 moc 163 Downcasting: SilnikTurbo * st; st = ( SilnikTurbo * )s; st->cisnieniedoladowania = 0.5; st pojemnosc 2400 lbcylindrow 5 moc 163 cisnieniedoladowania 0.9 Downcasting: konwersja wskazania na obiekt klasy bazowej do wskaźnika na klasę pochodną. Możliwe tylko poprzez konwersję typów wskaźników jawnie zapisaną przez programistę. 41

42 Wskaźniki pozwalają patrzeć na obiekt w różny sposób SilnikTurbo silt; s.pojemnosc = 2400; s.moc = 163; s.lbcylindrow = 5; s.cisnieniedoladowania = 0.9; Upcasting: Silnik * s; s = &silt; s->cisnieniedoladowania = 0.5; s silt : SilnikTurbo pojemnosc 2400 lbcylindrow 5 moc 163 cisnieniedoladowania 0.9 Wskaźnik s widzi obiekt silt tak: pojemnosc 2400 lbcylindrow 5 moc 163 Downcasting: SilnikTurbo * st; st = ( SilnikTurbo * )s; st->cisnieniedoladowania = 0.5; st Wskaźnik st widzi obiekt silt tak: pojemnosc 2400 lbcylindrow 5 moc 163 cisnieniedoladowania 0.9 W tym przypadku downcasting jest bezpieczny obiekt wskazywany przez s jest rzeczywiście obiektem klasy SilnikTurbo i downcasting odsłania przesłonięte pole cisnieniedoladowania. 42

43 Ale teraz będą kłopoty... Silnik sil; s.pojemnosc = 2400; s.moc = 163; s.lbcylindrow = 5; sil : Silnik pojemnosc 2400 lbcylindrow 5 moc 163 Zakotwiczenie wskaźnika: Wskaźnik s widzi obiekt silt tak: Silnik * s; s = &sil; s->cisnieniedoladowania = 0.5; s pojemnosc 2400 lbcylindrow 5 moc 163 Downcasting: Wskaźnik st widzi obiekt silt tak: SilnikTurbo * st; st = ( SilnikTurbo * )s; st->cisnieniedoladowania = 0.5; st Tego nie ma! pojemnosc 2400 lbcylindrow 5 moc 163 cisnieniedoladowania 0.9 W tym przypadku downcasting jest błędny obiekt wskazywany przez s nie jest obiektem klasy SilnikTurbo i downcasting produkuje nieistniejące pole cisnieniedoladowania. 43

44 Downcasting wykonywany poprzez dynamic_cast Nie do końca bezpieczne metody konwersji wskaźników: Silnik * s; SilnikTurbo * st; st = ( SilnikTurbo * )s; st = static_cast< SilnikTurbo * >( s ); st = reinterpret_cast< SilnikTurbo * >( s ); Rzutowanie z kontrolą jego poprawności: st = dynamic_cast< SilnikTurbo * >( s ); if( st!= 0 ) st->cisnieniedoladowania = 0.5; Operator dynamic_cast pozwala na konwersję wskaźników z kontrolą, czy taka konwersja może być przeprowadzona. Jeżeli możliwa jest konwersja do postaci wskaźnika na klasę pochodną, operator taką konwersję realizuje. Jeżeli konwersja nie może zostać zrealizowana, rezultatem operatora jest wartość zerowa. Mechanizm pozwalający na dynamic_cast, znany jest jako Run-Time Type Information RTTI. 44

45 Koncepcja polimorfizmu 45

46 Koncepcja polimorfizmu Słowo polimorfizm pochodzi od dwóch greckich słów: poly czyli wiele, morphos czyli postać. Polimorfizm oznacza zatem wielopostaciowość. Polimorfizm w programowaniu bywa bardzo różnie definiowany statyczny, dynamiczny, metod, typów, itp., itd.. Dla naszych potrzeba założymy, że polimorfizm w programowaniu obiektowym oznacza możliwość występowania obiektu w różnych jego wersjach, które mogą różnie reagować na ten sam komunikat. Polimorfizm to zatem zdolność obiektów do różnych zachowań, w zależności od bieżącego kontekstu wykonania programu. 46

47 Prosty przykład polimorfizmu różne postacie obiektu Runner * runner; runner = new Runner; runner->show(); runner->moveup(); delete runner; W języku C++ wykorzystanie wskaźników i referencji jest niezbędne dla polimorfizmu. Pierwsza postać obiektu wskazywanego, runner wskazuje na obiekt klasy Runner. runner = new RunnerWithTrace; runner->show(); runner->moveup(); delete runner; Druga postać obiektu wskazywanego, runner wskazuje na obiekt klasy RunnerWithTrace. 47

48 Prosty przykład polimorfizmu różne zachowanie obiektów Runner * runner; runner = new Runner; runner->show(); runner->moveup(); delete runner; runner = new RunnerWithTrace; runner->show(); runner->moveup(); delete runner; Wysyłamy komunikaty show() oraz moveup() do obiektów wskazywanych przez runner. Każdy z obiektów odpowiada wywołując własne wersje funkcji składowych. Polimorfizm obiekt wskazywany przez runner występuje w różnych postaciach, które reagują różnie na te same komunikaty. Przypomnienie: przy wywołaniu funkcji wirtualnych via wskaźnik (referencja ), o tym, która wersja funkcji zostanie wywołana decyduje typ obiektu wskazywanego a nie typ wskaźnika. 48

49 Polimorfizm konkretyzuje się w czasie wykonania programu Runner * runner; runner = new Runner; runner->show(); runner->moveup(); delete runner; runner = new RunnerWithTrace; runner->show(); runner->moveup(); delete runner; Nie wiadomo dokładnie, jaka jest konkretna postać obiektu. Nie wiadomo dokładnie, jak obiekty się zachowają. Wszystko okaże się w trakcie wykonania programu, to jest polimorfizm dynamiczny. Aby w C++ polimorfizm działał poprawnie należy: stosować dziedziczenie i odwoływać się do obiektów poprzez wskaźniki i referencje, wykorzystywać funkcje wirtualne, stosować upcasting oraz wtedy gdy trzeba i można downcasting. 48

50 Polimorfizm w akcji Należy napisać program wspomagający pracę technologa w firmie produkującej okna. Zadaniem programu jest: obliczanie łącznego pola powierzchni wszystkich skrzydeł okna, przybliżonej, łącznej długości profili, wymaganych do produkcji każdego ze skrzydeł. 49

51 Analiza obiektowa Stosując zasadę abstrakcji wyodrębniamy najistotniejsze cechy obiektów dla rozpatrywanego zagadnienia szyby to figury geometryczne a okno to ich złożenie. Łączna powierzchnia okna to, w przybliżeniu, suma pól figur opisujących szyby, Łączna długość profili to, w przybliżeniu, suma obwodów figur opisujących szyby. Trójkąt Kwadrat Prostokąt Prostokąt Obiekty rzeczywiste Abstrakcyjny model analityczny 50

52 Analiza obiektowa, cd... Realizacja programu sprowadza się do obliczeń pól powierzchni i obwodów obiektów, będących złożeniem elementarnych figur płaskich. Utworzyliśmy już klasy reprezentujące figury płaskie, Nie wiemy jak reprezentować ich złożenia. Trójkąt Kwadrat Prostokąt Prostokąt Kwadrat Prostokąt Prostokąt Trójkąt 51

53 Figury płaskie raz jeszcze budujemy hierarchię klas Rozpoczynamy od utworzenia nieco dziwnej klasy reprezentującej abstrakcyjną figurę geometryczną. Wyposażamy ją w funkcje obliczania pola i obwodu. class Figure public : Figure() double area() const return 0; double circumference() const return 0; const char * getname() const return "Figura"; ; Klasa Figure służyć będzie jak klasa bazowa dla specjalizowanych klas pochodnych, reprezentujących konkretne figury geometryczne. Jej istotą jest stwierdzenie, że każda figura geometryczna powinna umieć wyznaczać swoje pole i obwód, w charakterystyczny dla siebie sposób. Zatem każda z klas pochodnych, powinna redefiniować funkcje area i circumference, w odpowiedni dla tych klas sposób. Dodatkowo klasa Figure i jej pochodne posiadać będę funkcję getname(), jej rezultatem będzie nazwa klasy. 52

54 Klasa Square jako pochodna klasy Figure Klasa reprezentująca kwadrat będzie teraz klasą pochodną klasy Figure: class Square: public Figure public : Square( double startside = 0 ); void setside( double newside ); double getside(); double area() const; double circumference() const; const char * getname() const; private: double side; ; Redefinicja funkcji area i circumference i getname dla kwadratu: double Square::area() const return side * side; double Square::circumference() const return 4 * side; const char * Square::getName() const return "Kwadrat"; 53

55 Klasa Rectangle jako pochodna klasy Figure Klasa reprezentująca prostokąt będzie teraz klasą pochodną klasy Figure: class Rectangle: public Figure public : Rectangle( double startwidth = 0, double startheight = 0 ); void setwidth( double newwidth ); void setheight( double newheight ); double getwidth() const; double getheight() const; double area() const; double circumference() const; const char * getname() const; private: double width, height; ; Redefinicja funkcji area i circumference i getname dla prostokąta: double Rectangle::area() const return width * height; double Rectangle::circumference() const return 2 * width + 2 * height; const char * Rectangle::getName() const return "Prostokat"; 55

56 Klasa Triangle jako pochodna klasy Figure Klasa reprezentująca trójkąt będzie teraz klasą pochodną klasy Figure: class Triangle: public Figure public : Triangle( double startbase = 0, double startheight = 0 ); void setbase( double newbase ); void setheight( double newheight ); double getbase() const; double getheight() const; double area() const; double circumference() const; const char * getname() const; private: double base, height; ; Uwaga, zakładamy dla uproszczenia, że trójkątne szyby będą trójkątami prostokątnymi. Redefinicja funkcji area i circumference i getname dla trójkąta: double Triangle::area() const return 0.5 * base * height; double Triangle::circumference() const return sqrt( base * base + height * height ) + base + height; const char * Triangle::getName() const return "Trojkat"; 56

57 Hierarchia klas figur płaskich Figure +double area() +double circumference() +const char * getname() Rectangle Square Triangle +double area() +double circumference() +const char * getname() double height double width +double area() +double circumference() +const char * getname() double side +double area() +double circumference() +const char * getname() double base double width 57

58 Krok w stronę polimorfizmu upcasting z wykorzystaniem wskaźnika Załóżmy, że zdefiniowano wskaźnik do klasy bazowej Figure: Figure * fp; Załóżmy, że zdefiniowano obiekty klas pochodnych: Square s( 10 ); Rectangle r( 10, 20 ); Triangle t( 10,10 ); Wiemy już, że można przypisać do wskaźnika fp wskazanie na obiekt klasy pochodnej: fp = &s; fp = &r; fp = &t; // OK // OK // OK 58

59 Polimorfizm w akcji...? Figure * fp; Square s( 10 ); Rectangle r( 10, 20 ); Triangle t( 10,10 ); fp = &s; cout << endl << "Figura: " << fp->getname(); cout << endl << " Pole: " << fp->area(); cout << endl << " Obwod: " << fp->circumference(); fp = &r; cout << endl << "Figura: " << fp->getname(); cout << endl << " Pole: " << fp->area(); cout << endl << " Obwod: " << fp->circumference(); fp = &t; cout << endl << "Figura: " << fp->getname(); cout << endl << " Pole: " << fp->area(); cout << endl << " Obwod: " << fp->circumference(); Ale to nie działa! Obiekty zachowują się tak, jakby były obiektami klasy Figure! Dlaczego? 59

60 Zapomnieliśmy o funkcjach wirtualnych! Jest: class Figure public : Figure() double area() const return 0; double circumference() const return 0; const char * getname() const return "Figura"; ; Powinno być: class Figure public : Figure() virtual double area() const return 0; virtual double circumference() const return 0; virtual const char * getname() const return "Figura"; ; Nie ma polimorfizmu bez metod wirtualnych w klasach tworzących hierarchię dziedziczenia. 60

61 Wiązanie statyczne i funkcje niewirtualne raz jeszcze O tym która funkcja jest wywoływana decyduje kompilator na etapie kompilacji. Wywołanie ma taką samą postać jak wywołanie klasycznych funkcji w języku C. O tym która funkcja zostanie wywołana decyduje typ występujący w deklaracji zmiennej wskaźnikowej. Figure * fp; Square s( 10 ); fp = &s; cout << fp->area() << endl; cout << fp->circumference() << endl; Square Figure +double area() +double circumference() +const char * getname() Mimo iż klasa Square przedefiniowała obie funkcje i posiada ich własne wersje, nie zostaną one wywołane. +double area() +double circumference() +const char * getname() double side 61

62 Wiązanie dynamiczne i funkcje wirtualne raz jeszcze O tym która funkcja jest wywoływana decyduje typ obiektu wskazywanego. Funkcja wiązana dynamicznie musi być zadeklarowana jako wirtualna. Wystarczy, że słowo kluczowe virtual wystąpi w deklaracji klasy bazowej. Square Te funkcje zostały nadpisane w klasie pochodnej. Figure * fp; Square s( 10 ); fp = &s; cout << fp->area() << endl; cout << fp->circumference() << endl; Figure +double area() +double circumference() +const char * getname() +double area() +double circumference() +const char * getname() Klasa Square przedefiniowała obie funkcje wirtualne. To one właśnie zostaną wywołane a nie funkcje z klasy bazowej. double side 62

63 Jeszcze raz z funkcjami wirtualnymi... Figure * fp; Square s( 10 ); Rectangle r( 10, 20 ); Triangle t( 10,10 ); fp = &s; cout << endl << "Figura: " << fp->getname(); cout << endl << " Pole: " << fp->area(); cout << endl << " Obwod: " << fp->circumference(); fp = &r; cout << endl << "Figura: " << fp->getname(); cout << endl << " Pole: " << fp->area(); cout << endl << " Obwod: " << fp->circumference(); fp = &t; cout << endl << "Figura: " << fp->getname(); cout << endl << " Pole: " << fp->area(); cout << endl << " Obwod: " << fp->circumference(); Polimorfizm = dziedziczenie, redefinicja metod wirtualnych, wskaźniki (referencje) i upcasting. 62

64 Jak to wszystko wykorzystać w programie okiennym? Zadany jest układ okna oraz wymiary jego ościeżnic. Jedna ościeżnica jest kwadratowa (bok 50cm), pozostałe trzy prostokątne (70x50 cm, 50x100 cm i 70x100 cm). Należy wyznaczyć łączną powierzchnię szyb i długość profili

65 Jak reprezentować informacje o oknie? const const int int itemno itemno == 4; 4; 50 Figure Figure ** win[ win[ itemno itemno ]; ]; win Prostokąt Kwadrat 70 Prostokąt Prostokąt 65

66 Jak to wygląda w pamięci operacyjnej? win Square +double area() +double circumference() +const char * getname() double side: 50 Rectangle +double area() +double circumference() +const char * getname() double height: 70 double width: 100 Rectangle +double area() +double circumference() +const char * getname() double height: 50 double width: 70 Rectangle +double area() +double circumference() +const char * getname() double height: 50 double width:

67 Definiowanie elementów okna, obliczenia, sprzątanie // Okre ś lenie liczby elementów const int itemno = 4; // Tablica wka ź ników na elementy okna Figure * win[ itemno ]; // Przydział pami ę ci dla elementów okna win[ 0 ] = new Square( 50 ); win[ 1 ] = new Rectangle( 50, 70 ); win[ 2 ] = new Rectangle( 50, 100 ); win[ 3 ] = new Rectangle( 70, 100 ); // Oblicz co trzeba i wyprowadz do strumienia wyj ś ciowego calcandshowwininfo( win, 4 ); // Zwolnij pami ę ć przydzielon ą elementom okna for( int i = 0; i < itemno; delete win[ i++] ) ; 67

68 Funkcja calcandshowwininfo void calcandshowwininfo( Figure * window[], int numofsash ) // Tutaj ł ą czna powierzchnia szyb i długo ś ć profili double totalarea = 0, totalcircum = 0; // Zliczanie powierzchni i długo ś ci for( int i = 0; i < numofsash; i++ ) totalarea += window[ i ]->area(); totalcircum += window[ i ]->circumference(); // Wyprowadzanie wyników obliczeń cout << "Powierzchnia szyb : " << totalarea << endl; cout << "Dlugosc profili : " << totalcircum << endl; cout << endl; 68

69 Iteracja krok po kroku for( int i = 0; i < numofsash; i++ ) totalarea += window[ i ]->area(); totalcircum += window[ i ]->circumference(); i win Square Rectangle +double area() +double circumference() +double area() +double circumference() double Square::area() const double height: 70 double side: 50 double width: 100 return side * side; double Rectangle Rectangle Square::circumference() const +double area() +double area() +double return circumference() 4 * side; +double circumference() double height: 50 double height: 50 double width: 70 double width:

70 Iteracja krok po kroku for( int i = 0; i < numofsash; i++ ) totalarea += window[ i ]->area(); totalcircum += window[ i ]->circumference(); i 1 win Square Rectangle +double area() +double area() +double circumference() double Rectangle::area() +double const circumference() double side: 50 return double height: 70 width * height; double width: 100 double Rectangle::circumference() Rectangle const Rectangle return 2 * width + 2 * height; +double area() +double area() +double circumference() +double circumference() double height: 50 double width: 70 double height: 50 double width:

71 Iteracja krok po kroku for( int i = 0; i < numofsash; i++ ) totalarea += window[ i ]->area(); totalcircum += window[ i ]->circumference(); i 2 win Square +double area() +double circumference() Rectangle::area() const double return side: width 50* height; double Rectangle::circumference() const Rectangle return 2 * width + 2 * height; +double area() +double circumference() double height: 50 double width: 70 Rectangle +double area() +double circumference() double height: 50 double width: 100 Rectangle +double area() +double circumference() double height: 70 double width:

72 Iteracja krok po kroku for( int i = 0; i < numofsash; i++ ) totalarea += window[ i ]->area(); totalcircum += window[ i ]->circumference(); i 3 win Square +double area() +double circumference() Rectangle +double area() +double circumference() double height: 70 double side: 50 double width: 100 double Rectangle::area() const return Rectangle width * height; Rectangle +double area() +double area() double +double Rectangle::circumference() circumference() +double circumference() const double return height: 2 * width double * height; height: 50 double width: 70 double width:

73 Polimorfizm krótkie podsumowanie Polimorfizm zakłada, że jedna funkcja składowa występować może we wielu wersjach. Wersje te definiowane są w klasach pochodnych, polimorfizm zakłada zatem wykorzystanie dziedziczenia. Wysłanie do obiektu komunikatu o określonej nazwie (np. area) może spowodować wykonanie różnych akcji (wywołanie różnych wersji funkcji składowej) w zależności od kontekstu wywołania. Kontekst wywołania zależy od tego, na obiekt jakiej klasy wskazuje zmienna wskaźnikowa, albo z jakim obiektem skojarzona jest referencja. W języku C++ polimorfizm jest realizowany z wykorzystaniem funkcji wirtualnych i dostępny jest przy wykorzystaniu odwołań wskaźnikowych lub referencyjnych. Funkcje wirtualne wywoływane są na zasadzie wiązania dynamicznego. C++ jest hybrydowym językiem programowania. Zawiera mechanizmy obiektowe ale nie wymusza ich wykorzystania. Pozostawia również programiście wybór, czy stosować wiązanie styczne czy dynamiczne. 54

Projektowanie obiektowe. Roman Simiński Klasy abstrakcyjne Interfejsy

Projektowanie obiektowe. Roman Simiński  Klasy abstrakcyjne Interfejsy Projektowanie obiektowe Roman Simiński roman.siminski@us.edu.pl www.siminskionline.pl Klasy abstrakcyjne Interfejsy Klasa abstrakcyjna po co? W programowaniu obiektowym wykorzystywane są: Abstrakcja programowanie

Bardziej szczegółowo

Projektowanie obiektowe. Roman Simiński Polimorfizm

Projektowanie obiektowe. Roman Simiński   Polimorfizm Projektowanie obiektowe Roman Simiński roman.siminski@us.edu.pl www.siminskionline.pl Polimorfizm Koncepcja polimorfizmu Słowo polimorfizm pochodzi od dwóch greckich słów: poly czyli wiele, morphos czyli

Bardziej szczegółowo

Zaawansowane programowanie w języku C++ Programowanie obiektowe

Zaawansowane programowanie w języku C++ Programowanie obiektowe Zaawansowane programowanie w języku C++ Programowanie obiektowe Prezentacja jest współfinansowana przez Unię Europejską w ramach Europejskiego Funduszu Społecznego w projekcie pt. Innowacyjna dydaktyka

Bardziej szczegółowo

TEMAT : KLASY DZIEDZICZENIE

TEMAT : KLASY DZIEDZICZENIE TEMAT : KLASY DZIEDZICZENIE Wprowadzenie do dziedziczenia w języku C++ Język C++ możliwa tworzenie nowej klasy (nazywanej klasą pochodną) w oparciu o pewną wcześniej zdefiniowaną klasę (nazywaną klasą

Bardziej szczegółowo

PARADYGMATY PROGRAMOWANIA Wykład 4

PARADYGMATY PROGRAMOWANIA Wykład 4 PARADYGMATY PROGRAMOWANIA Wykład 4 Metody wirtualne i polimorfizm Metoda wirualna - metoda używana w identyczny sposób w całej hierarchii klas. Wybór funkcji, którą należy wykonać po wywołaniu metody wirtualnej

Bardziej szczegółowo

Programowanie obiektowe w języku C++

Programowanie obiektowe w języku C++ Programowanie obiektowe w języku C++ Roman Simiński roman.siminski@us.edu.pl www.siminskionline.pl Klasy i obiekty pierwsze kroki Problem Przewidywane jest napisanie obiektowej wersji programu, realizującego

Bardziej szczegółowo

Wprowadzenie do programowanie obiektowego w języku C++

Wprowadzenie do programowanie obiektowego w języku C++ Wprowadzenie do programowanie obiektowego w języku C++ Część czwarta Autor Roman Simiński Kontakt roman.siminski@us.edu.pl www.us.edu.pl/~siminski Niniejsze opracowanie zawiera skrót treści wykładu, lektura

Bardziej szczegółowo

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej. Polimorfizm jest filarem programowania obiektowego, nie tylko jeżeli chodzi o język C++. Daje on programiście dużą elastyczność podczas pisania programu. Polimorfizm jest ściśle związany z metodami wirtualnymi.

Bardziej szczegółowo

Programowanie obiektowe w języku

Programowanie obiektowe w języku Programowanie obiektowe w języku C++ Stanisław Gepner sgepner@meil.pw.edu.pl Dziedziczenie Wstęp Zacznijmy od przykładu Przykład rolniczy Każde zwierzątko wydaje dźwięk Każde się tak samo porusza Musimy

Bardziej szczegółowo

1 Definiowanie prostych klas

1 Definiowanie prostych klas Ćwiczenie 1 1 Definiowanie prostych klas Ćwiczenie to poświęcone jest poznaniu podstawowych zagadnień związanych z definiowaniem prostych klas. Obejmuje m.in. ćwiczenia pozwalające opanować definiowanie

Bardziej szczegółowo

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost; Klasy w C++ są bardzo ważnym narzędziem w rękach programisty. Klasy są fundamentem programowania obiektowego. Z pomocą klas będziesz mógł tworzyć lepszy kod, a co najważniejsze będzie on bardzo dobrze

Bardziej szczegółowo

1 Dziedziczenie. 1.1 Koncepcja dziedziczenia. Ćwiczenie 3

1 Dziedziczenie. 1.1 Koncepcja dziedziczenia. Ćwiczenie 3 Ćwiczenie 3 1 Dziedziczenie Ćwiczenie to poświęcone jest poznaniu podstawowych zagadnień związanych dziedziczeniem procesem budowania nowych klas, w oparciu o klasy istniejące. Obejmuje m.in. ćwiczenia

Bardziej szczegółowo

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Składnia C++ Programowanie Obiektowe Mateusz Cicheński Składnia C++ Programowanie Obiektowe Mateusz Cicheński Klasy i modyfikatory dostępu Przesłanianie metod Polimorfizm Wskaźniki Metody wirtualne Metody abstrakcyjne i interfejsy Przeciążanie operatorów Słowo

Bardziej szczegółowo

Mechanizm dziedziczenia

Mechanizm dziedziczenia Mechanizm dziedziczenia Programowanie obiektowe jako realizacja koncepcji ponownego wykorzystania kodu Jak przebiega proces dziedziczenia? Weryfikacja formalna poprawności dziedziczenia Realizacja dziedziczenia

Bardziej szczegółowo

Projektowanie obiektowe. Roman Simiński Wzorce projektowe Wybrane wzorce strukturalne

Projektowanie obiektowe. Roman Simiński  Wzorce projektowe Wybrane wzorce strukturalne Projektowanie obiektowe Roman Simiński roman.siminski@us.edu.pl www.siminskionline.pl Wzorce projektowe Wybrane wzorce strukturalne Fasada Facade Pattern 2 Wzorzec Fasada Facade Pattern koncepcja 3 Wzorzec

Bardziej szczegółowo

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki Dariusz Brzeziński Politechnika Poznańska, Instytut Informatyki zaprojektowany jako rozszerzenie języka C o obiektowe mechanizmy abstrakcji danych jest to język pozwalający na programowanie zarówno proceduralne

Bardziej szczegółowo

Podstawy Programowania Obiektowego

Podstawy Programowania Obiektowego Podstawy Programowania Obiektowego Wprowadzenie do programowania obiektowego. Pojęcie struktury i klasy. Spotkanie 03 Dr inż. Dariusz JĘDRZEJCZYK Tematyka wykładu Idea programowania obiektowego Definicja

Bardziej szczegółowo

Wykład 8: klasy cz. 4

Wykład 8: klasy cz. 4 Programowanie obiektowe Wykład 8: klasy cz. 4 Dynamiczne tworzenie obiektów klas Składniki statyczne klas Konstruktor i destruktory c.d. 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD

Bardziej szczegółowo

Programowanie obiektowe Wykład 6. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14

Programowanie obiektowe Wykład 6. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Dariusz Wardowski dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Wirtualne destruktory class A int* a; A(int _a) a = new int(_a);} virtual ~A() delete a;} class B: public A double* b;

Bardziej szczegółowo

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi EGZAMIN PIERWSZY (25 CZERWCA 2013) JĘZYK C++ poprawiam ocenę pozytywną z egzaminu 0 (zakreśl poniżej x) 1. Wśród poniższych wskaż poprawną formę definicji

Bardziej szczegółowo

Wykład V. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Wykład V. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej Wykład V - semestr II Kierunek Informatyka Wydział Matematyki Stosowanej Politechniki Śląskiej Gliwice, 2014 c Copyright 2014 Janusz Słupik Programowanie obiektowe Dziedziczenie (inheritance) - mechanizm

Bardziej szczegółowo

Wprowadzenie do programowanie obiektowego w języku C++

Wprowadzenie do programowanie obiektowego w języku C++ Wprowadzenie do programowanie obiektowego w języku C++ Część druga Obiekty i klasy Autor Roman Simiński Kontakt roman.siminski@us.edu.pl www.us.edu.pl/~siminski Niniejsze opracowanie zawiera skrót treści

Bardziej szczegółowo

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie? 1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie? a) konstruktor b) referencje c) destruktor d) typy 2. Które z poniższych wyrażeń są poprawne dla klasy o nazwie

Bardziej szczegółowo

Dziedziczenie jednobazowe, poliformizm

Dziedziczenie jednobazowe, poliformizm Dziedziczenie jednobazowe, poliformizm 1. Dziedziczenie jednobazowe 2. Polimorfizm część pierwsza 3. Polimorfizm część druga Zofia Kruczkiewicz, ETE8305_6 1 Dziedziczenie jednobazowe, poliformizm 1. Dziedziczenie

Bardziej szczegółowo

Rozdział 4 KLASY, OBIEKTY, METODY

Rozdział 4 KLASY, OBIEKTY, METODY Rozdział 4 KLASY, OBIEKTY, METODY Java jest językiem w pełni zorientowanym obiektowo. Wszystkie elementy opisujące dane, za wyjątkiem zmiennych prostych są obiektami. Sam program też jest obiektem pewnej

Bardziej szczegółowo

Programowanie obiektowe - 1.

Programowanie obiektowe - 1. Programowanie obiektowe - 1 Mariusz.Masewicz@cs.put.poznan.pl Programowanie obiektowe Programowanie obiektowe (ang. object-oriented programming) to metodologia tworzenia programów komputerowych, która

Bardziej szczegółowo

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki Dariusz Brzeziński Politechnika Poznańska, Instytut Informatyki Object-oriented programming Najpopularniejszy obecnie styl (paradygmat) programowania Rozwinięcie koncepcji programowania strukturalnego

Bardziej szczegółowo

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut.

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut. Dziedziczenie Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut. Rozpatrzmy przykład przedstawiający klasy Student oraz Pracownik: class Student class Pracownik

Bardziej szczegółowo

Podstawy programowania w języku C++

Podstawy programowania w języku C++ Podstawy programowania w języku C++ Część dziewiąta Tablice a zmienne wskaźnikowe Wersja skrócona, tylko C++ Autor Roman Simiński Kontakt roman.siminski@us.edu.pl www.us.edu.pl/~siminski Niniejsze opracowanie

Bardziej szczegółowo

Klasy abstrakcyjne i interfejsy

Klasy abstrakcyjne i interfejsy Klasy abstrakcyjne i interfejsy Streszczenie Celem wykładu jest omówienie klas abstrakcyjnych i interfejsów w Javie. Czas wykładu 45 minut. Rozwiązanie w miarę standardowego zadania matematycznego (i nie

Bardziej szczegółowo

Lab 9 Podstawy Programowania

Lab 9 Podstawy Programowania Lab 9 Podstawy Programowania (Kaja.Gutowska@cs.put.poznan.pl) Wszystkie kody/fragmenty kodów dostępne w osobnym pliku.txt. Materiały pomocnicze: Wskaźnik to specjalny rodzaj zmiennej, w której zapisany

Bardziej szczegółowo

TEMAT : KLASY POLIMORFIZM

TEMAT : KLASY POLIMORFIZM TEMAT : KLASY POLIMORFIZM 1. Wprowadzenie do polimorfizmu i funkcji wirtualnych w języku C++ Język C++ zakłada, że w pewnych przypadkach uzasadnione jest tworzenie klas, których reprezentanci w programie

Bardziej szczegółowo

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018 Informatyka I Klasy i obiekty. Podstawy programowania obiektowego dr inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2018 Plan wykładu Pojęcie klasy Deklaracja klasy Pola i metody klasy

Bardziej szczegółowo

Programowanie obiektowe i zdarzeniowe

Programowanie obiektowe i zdarzeniowe Marek Tabędzki Programowanie obiektowe i zdarzeniowe 1/23 Programowanie obiektowe i zdarzeniowe wykład 6 polimorfizm Na poprzednim wykładzie: dziedziczenie jest sposobem na utworzenie nowej klasy na podstawie

Bardziej szczegółowo

Polimorfizm. dr Jarosław Skaruz

Polimorfizm. dr Jarosław Skaruz Polimorfizm dr Jarosław Skaruz http://jareks.ii.uph.edu.pl jaroslaw@skaruz.com O czym będzie? finalne składowe klasy abstrakcyjne interfejsy polimorfizm Finalne składowe Domyślnie wszystkie pola i metody

Bardziej szczegółowo

Dziedziczenie. Tomasz Borzyszkowski

Dziedziczenie. Tomasz Borzyszkowski Dziedziczenie Tomasz Borzyszkowski Podstawy Zobacz: Dziedzictwo1.java Dziedzictwo2.java Dziedziczenie jest jedną z podstawowych cech OOP ponieważ umożliwia łatwe implementowanie klasyfikacji hierarchicznych.

Bardziej szczegółowo

Wyjątki (exceptions)

Wyjątki (exceptions) Instrukcja laboratoryjna nr 6 Programowanie w języku C 2 (C++ poziom zaawansowany) Wyjątki (exceptions) dr inż. Jacek Wilk-Jakubowski mgr inż. Maciej Lasota dr inż. Tomasz Kaczmarek Wstęp Wyjątki (ang.

Bardziej szczegółowo

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np Klasy Klasa jest nowym typem danych zdefiniowanym przez użytkownika Wartości takiego typu nazywamy obiektami Najprostsza klasa jest po prostu strukturą, np struct Zespolona { Klasy jako struktury z operacjami

Bardziej szczegółowo

Informatyka I. Dziedziczenie. Nadpisanie metod. Klasy abstrakcyjne. Wskaźnik this. Metody i pola statyczne. dr inż. Andrzej Czerepicki

Informatyka I. Dziedziczenie. Nadpisanie metod. Klasy abstrakcyjne. Wskaźnik this. Metody i pola statyczne. dr inż. Andrzej Czerepicki Informatyka I Dziedziczenie. Nadpisanie metod. Klasy abstrakcyjne. Wskaźnik this. Metody i pola statyczne. dr inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2017 Dziedziczenie klas

Bardziej szczegółowo

Interfejsy i klasy wewnętrzne

Interfejsy i klasy wewnętrzne Interfejsy i klasy wewnętrzne mgr Tomasz Xięski, Instytut Informatyki, Uniwersytet Śląski Katowice, 2011 Interfejs klasy sposób komunikacji z jej obiektami (zestaw składowych publicznych). Określa on zestaw

Bardziej szczegółowo

Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego. Iwona Kochaoska

Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego. Iwona Kochaoska Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego Iwona Kochaoska Programowanie Obiektowe Programowanie obiektowe (ang. object-oriented programming) - metodyka tworzenia programów komputerowych,

Bardziej szczegółowo

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016 Wstęp - wykład 0 22 lutego 2016 Historia Simula 67 język zaprojektowany do zastosowan symulacyjnych; Smalltalk 80 pierwszy język w pełni obiektowy; Dodawanie obiektowości do języków imperatywnych: Pascal

Bardziej szczegółowo

JAVA W SUPER EXPRESOWEJ PIGUŁCE

JAVA W SUPER EXPRESOWEJ PIGUŁCE JAVA W SUPER EXPRESOWEJ PIGUŁCE Obiekt Obiekty programowe to zbiór własności i zachowań (zmiennych i metod). Podobnie jak w świecie rzeczywistym obiekty posiadają swój stan i zachowanie. Komunikat Wszystkie

Bardziej szczegółowo

Zaawansowane programowanie w C++ (PCP)

Zaawansowane programowanie w C++ (PCP) Zaawansowane programowanie w C++ (PCP) Wykład 3 - polimorfizm. dr inż. Robert Nowak - p. 1/14 Powtórzenie Powtórzenie: klasy autonomiczne: konstruktor, konstruktor kopiujacy, operator przypisania, destruktor

Bardziej szczegółowo

Wykład 5: Klasy cz. 3

Wykład 5: Klasy cz. 3 Programowanie obiektowe Wykład 5: cz. 3 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD - podstawy Konstruktor i destruktor (część I) 2 Konstruktor i destruktor KONSTRUKTOR Dla przykładu

Bardziej szczegółowo

Programowanie w języku C++

Programowanie w języku C++ Programowanie w języku C++ Część siódma Autor Roman Simiński Kontakt roman.siminski@us.edu.pl www.us.edu.pl/~siminski Niniejsze opracowanie zawiera skrót treści wykładu, lektura tych materiałów nie zastąpi

Bardziej szczegółowo

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016 Wykład 2 17 marca 2016 Dziedziczenie Klasy bazowe i potomne Dziedziczenie jest łatwym sposobem rozwijania oprogramowania. Majac klasę bazowa możemy ja uszczegółowić (dodać nowe pola i metody) nie przepisujac

Bardziej szczegółowo

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut. Konstruktory Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut. Rozpatrzmy przykład przedstawiający klasę Prostokat: class

Bardziej szczegółowo

C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm POLIMORFIZM

C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm POLIMORFIZM POLIMORFIZM Podstawowe pytanie, które nieustannie ma towarzyszyć autorowi programowi: czy gdyby nagle okazało się, że jest więcej... (danych na wejściu, typów danych, czynności, które program ma wykonać,

Bardziej szczegółowo

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Java - tablice, konstruktory, dziedziczenie i hermetyzacja Java - tablice, konstruktory, dziedziczenie i hermetyzacja Programowanie w językach wysokiego poziomu mgr inż. Anna Wawszczak PLAN WYKŁADU zmienne tablicowe konstruktory klas dziedziczenie hermetyzacja

Bardziej szczegółowo

Typy zmiennych proste i złożone. Programowanie komputerów. Tablica. Złożone typy zmiennych. Klasa. Struktura

Typy zmiennych proste i złożone. Programowanie komputerów. Tablica. Złożone typy zmiennych. Klasa. Struktura Programowanie komputerów Programowanie obiektowe. Typy zmiennych proste i złożone Typy zmiennych "wbudowane", tj. identyfikowane przez słowa kluczowe, są określane jako proste: int short long float double

Bardziej szczegółowo

Podstawy programowania w języku C++

Podstawy programowania w języku C++ Podstawy programowania w języku C++ Część ósma Zmienne wskaźnikowe koncepcja, podstawowe zastosowania Wersja skrócona, tylko C++ Autor Roman Simiński Kontakt roman.siminski@us.edu.pl www.us.edu.pl/~siminski

Bardziej szczegółowo

Wstęp do programowania obiektowego, wykład 7

Wstęp do programowania obiektowego, wykład 7 Wstęp do programowania obiektowego, wykład 7 Klasy i funkcje abstrakcyjne Przeciążanie funkcji Definiowanie i interpretacja złożonych typów danych w C++ Wskaźniki do funkcji 1 KLASA ABSTRAKCYJNA 2 Klasa

Bardziej szczegółowo

Programowanie 2. Język C++. Wykład 3.

Programowanie 2. Język C++. Wykład 3. 3.1 Programowanie zorientowane obiektowo... 1 3.2 Unie... 2 3.3 Struktury... 3 3.4 Klasy... 4 3.5 Elementy klasy... 5 3.6 Dostęp do elementów klasy... 7 3.7 Wskaźnik this... 10 3.1 Programowanie zorientowane

Bardziej szczegółowo

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Składnia C++ Programowanie Obiektowe Mateusz Cicheński Składnia C++ Programowanie Obiektowe Mateusz Cicheński Klasy i modyfikatory dostępu Przesłanianie metod Polimorfizm Wskaźniki Metody wirtualne Metody abstrakcyjne i interfejsy Konstruktory i destruktory

Bardziej szczegółowo

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami 1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami Celem tych zajęć jest zrozumienie i oswojenie z technikami programowania przy pomocy wskaźników w języku C++. Proszę przeczytać rozdział 8.

Bardziej szczegółowo

Identyfikacje typu na etapie. wykonania (RTTI)

Identyfikacje typu na etapie. wykonania (RTTI) Identyfikacje typu na etapie (Run Time Type Identification) wykonania (RTTI) Może powstać taka sytuacje, gdy w trakcie kompilacji typ obiektu nie jest znany. C++ implementuje polimorfizm poprzez hierarchie

Bardziej szczegółowo

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Polimorfizm, metody wirtualne i klasy abstrakcyjne Programowanie obiektowe Polimorfizm, metody wirtualne i klasy abstrakcyjne Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej pawel.rogalinski pwr.wroc.pl Polimorfizm,

Bardziej szczegółowo

Klasa dziedzicząca posiada wszystkie cechy klasy bazowej (plus swoje własne) dodawanie nowego kodu bez edycji (i ewentualnego wprowadzania

Klasa dziedzicząca posiada wszystkie cechy klasy bazowej (plus swoje własne) dodawanie nowego kodu bez edycji (i ewentualnego wprowadzania Programowanie przyrostowe Rzutowanie w górę Zaleta dziedziczenia i kompozycji jest programowanie przyrostowe: Klasa dziedzicząca posiada wszystkie cechy klasy bazowej (plus swoje własne) dodawanie nowego

Bardziej szczegółowo

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej Programowanie obiektowe Interfejsy Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej pawel.rogalinski pwr.wroc.pl Interfejsy Autor: Paweł Rogaliński Instytut Informatyki,

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe Wykład 2 Marcin Młotkowski 4 marca 2015 Plan wykładu 1 2 3 4 5 Marcin Młotkowski Programowanie obiektowe 2 / 47 Krótki opis C Obiektowy, z kontrolą typów; automatyczne odśmiecanie;

Bardziej szczegółowo

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu. Zrozumienie funkcji danych statycznych jest podstawą programowania obiektowego. W niniejszym artykule opiszę zasadę tworzenia klas statycznych w C#. Oprócz tego dowiesz się czym są statyczne pola i metody

Bardziej szczegółowo

Mechanizm dziedziczenia

Mechanizm dziedziczenia Mechanizm dziedziczenia Programowanie obiektowe jako realizacja koncepcji ponownego wykorzystania kodu Jak przebiega proces dziedziczenia? Weryfikacja formalna poprawności dziedziczenia Realizacja dziedziczenia

Bardziej szczegółowo

Wykład 4: Klasy i Metody

Wykład 4: Klasy i Metody Wykład 4: Klasy i Metody Klasa Podstawa języka. Każde pojęcie które chcemy opisać w języku musi być zawarte w definicji klasy. Klasa definiuje nowy typ danych, których wartościami są obiekty: klasa to

Bardziej szczegółowo

Operator przypisania. Jest czym innym niż konstruktor kopiujący!

Operator przypisania. Jest czym innym niż konstruktor kopiujący! Operator przypisania Jest czym innym niż konstruktor kopiujący! Domyślnie jest zdefiniowany jako przypisanie składowa po składowej (zatem niekoniecznie bajt po bajcie). Dla klasy X definiuje się jako X&

Bardziej szczegółowo

PHP 5 język obiektowy

PHP 5 język obiektowy PHP 5 język obiektowy Wprowadzenie Klasa w PHP jest traktowana jak zbiór, rodzaj różnych typów danych. Stanowi przepis jak stworzyć konkretne obiekty (instancje klasy), jest definicją obiektów. Klasa reprezentuje

Bardziej szczegółowo

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak Java język programowania obiektowego Programowanie w językach wysokiego poziomu mgr inż. Anna Wawszczak 1 Język Java Język Java powstał w roku 1995 w firmie SUN Microsystems Java jest językiem: wysokiego

Bardziej szczegółowo

Wykład 9: Polimorfizm i klasy wirtualne

Wykład 9: Polimorfizm i klasy wirtualne Programowanie obiektowe Wykład 9: i klasy wirtualne 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD Programowanie obiektowe i metody wirtualne 2 W programowaniu obiektowym polimorfizm

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Laboratorium z przedmiotu Programowanie obiektowe - zestaw 02 Cel zajęć. Celem zajęć jest zapoznanie z praktycznymi aspektami projektowania oraz implementacji klas i obiektów z wykorzystaniem dziedziczenia.

Bardziej szczegółowo

WSNHiD, Programowanie 2 Lab. 2 Język Java struktura programu, dziedziczenie, abstrakcja, polimorfizm, interfejsy

WSNHiD, Programowanie 2 Lab. 2 Język Java struktura programu, dziedziczenie, abstrakcja, polimorfizm, interfejsy WSNHiD, Programowanie 2 Lab. 2 Język Java struktura programu, dziedziczenie, abstrakcja, polimorfizm, interfejsy Pojęcie klasy Program napisany w języku Java składa się ze zbioru klas. Każda klasa zawiera

Bardziej szczegółowo

Definiowanie własnych klas

Definiowanie własnych klas Programowanie obiektowe Definiowanie własnych klas Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej pawel.rogalinski @ pwr.wroc.pl Definiowanie własnych klas Autor:

Bardziej szczegółowo

Szablony funkcji i szablony klas

Szablony funkcji i szablony klas Bogdan Kreczmer bogdan.kreczmer@pwr.wroc.pl Zakład Podstaw Cybernetyki i Robotyki Instytut Informatyki, Automatyki i Robotyki Politechnika Wrocławska Kurs: Copyright c 2011 Bogdan Kreczmer Niniejszy dokument

Bardziej szczegółowo

Wprowadzenie w dziedziczenie. Klasa D dziedziczy klasę B: Klasa B klasa bazowa (base class), klasa D klasa pochodna (derived class).

Wprowadzenie w dziedziczenie. Klasa D dziedziczy klasę B: Klasa B klasa bazowa (base class), klasa D klasa pochodna (derived class). Wprowadzenie w dziedziczenie Klasa D dziedziczy klasę B: B klasa bazowa D klasa pochodna Klasa B klasa bazowa (base class), klasa D klasa pochodna (derived class). Najpierw jest tworzona klasa bazowa,

Bardziej szczegółowo

Programowanie 2. Język C++. Wykład 9.

Programowanie 2. Język C++. Wykład 9. 9.1 Ukrywanie metod, metody nadpisane... 1 9.2 Metody wirtualne, wirtualny destruktor... 2 9.3 Metody czysto wirtualne... 6 9.4 Klasy abstrakcyjne... 7 9.5 Wielodziedziczenie... 9 9.1 Ukrywanie metod,

Bardziej szczegółowo

> C++ wskaźniki. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017

> C++ wskaźniki. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017 > C++ wskaźniki Dane: Iwona Polak iwona.polak@us.edu.pl Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017 >??? Co to jest WSKAŹNIK? ++ wskaźniki 2 / 20 >??? Co to jest WSKAŹNIK? To po prostu ADRES

Bardziej szczegółowo

Programowanie obiektowe

Programowanie obiektowe Programowanie obiektowe IV. Interfejsy i klasy wewnętrzne Małgorzata Prolejko OBI JA16Z03 Plan Właściwości interfejsów. Interfejsy a klasy abstrakcyjne. Klonowanie obiektów. Klasy wewnętrzne. Dostęp do

Bardziej szczegółowo

Programowanie Obiektowe i C++

Programowanie Obiektowe i C++ Programowanie Obiektowe i C++ Marcin Benke Instytut Informatyki UW 6.11.2006 Marcin Benke (IIUW) Programowanie Obiektowe i C++ 6.11.2006 1 / 138 Operator przypisania Jest czym innym niż konstruktor kopiujacy!

Bardziej szczegółowo

PARADYGMATY PROGRAMOWANIA Wykład 2

PARADYGMATY PROGRAMOWANIA Wykład 2 PARADYGMATY PROGRAMOWANIA Wykład 2 Definiowanie klas w C++ - ciąg dalszy Lista inicjalizująca konstruktora Przeznaczenie - do inicjalizacji pól klasy z kwalifikatorem const i inicjalizacji obiektów składowych

Bardziej szczegółowo

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1 Podstawy programowania. Wykład Funkcje Krzysztof Banaś Podstawy programowania 1 Programowanie proceduralne Pojęcie procedury (funkcji) programowanie proceduralne realizacja określonego zadania specyfikacja

Bardziej szczegółowo

Wykład 1. Program przedmiotu. Programowanie Obiektowe (język C++) Literatura. Program przedmiotu c.d.:

Wykład 1. Program przedmiotu. Programowanie Obiektowe (język C++) Literatura. Program przedmiotu c.d.: Program przedmiotu Programowanie Obiektowe (język C++) Wykład 1. Definiowanie prostych klas. Przykłady. Przypomnienie: typy referencyjne, domyślne wartości argumentów, przeciąŝanie funkcji. Konstruktory,

Bardziej szczegółowo

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27 Programowanie w C++ Wykład 14 Katarzyna Grzelak 3 czerwca 2019 K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27 Na ostatnim wykładzie: Konstruktor standardowy (domyślny) to taki, który nie ma żadnych argumentów

Bardziej szczegółowo

Język C++ wykład VI. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VI. dr Jarosław Mederski.

Język C++ wykład VI. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VI. dr Jarosław Mederski. - - uzupełnienie notatek: dr Jerzy Białkowski - - 1-2 - - - 1 #include 2 #include 3 # include 4 using namespace std ; 5 6 class Punkt { 7 8 private : 9 double

Bardziej szczegółowo

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

Jak napisać program obliczający pola powierzchni różnych figur płaskich? Część IX C++ Jak napisać program obliczający pola powierzchni różnych figur płaskich? Na początku, przed stworzeniem właściwego kodu programu zaprojektujemy naszą aplikację i stworzymy schemat blokowy

Bardziej szczegółowo

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość 1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość 2. Poprawna definicja wskażnika b to: a) float *a, **b = &a; b) float

Bardziej szczegółowo

Wykład 9: Metody wirtualne i polimorfizm

Wykład 9: Metody wirtualne i polimorfizm Języki programowania C i C++ Wykład 9: Metody wirtualne i polimorfizm 1 dr Artur Bartoszewski - Języki C i C++, sem. 1I- WYKŁAD Podstawy programowania w C++ 2 to funkcje składowe, które przydają się szczególnie,

Bardziej szczegółowo

C++ - [4-7] Polimorfizm

C++ - [4-7] Polimorfizm Slajd 1 z 14 C++ - [4-7] Polimorfizm Nysa 2004-2013. Autor: Wojciech Galiński. wersja dnia 20 maja 2013 r. Slajd 2 z 14 Polimorfizm i klasa polimorficzna POLIMORFIZM (cytat z Wikipedii) (wielopostaciowość)

Bardziej szczegółowo

wykład V uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C++ klasy i obiekty wykład V dr Jarosław Mederski Spis Język C++ - klasy

wykład V uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C++ klasy i obiekty wykład V dr Jarosław Mederski Spis Język C++ - klasy i obiekty Programowanie i obiekty uzupełnienie notatek: dr Jerzy Białkowski i obiekty 1 2 3 4 i obiekty Obiektowość języka C++ Na tym wykładzie poznamy: ˆ Klasa (w języku C++ rozszerzenie struktury, typ

Bardziej szczegółowo

Programowanie w Javie 1 Wykład i Ćwiczenia 3 Programowanie obiektowe w Javie cd. Płock, 16 października 2013 r.

Programowanie w Javie 1 Wykład i Ćwiczenia 3 Programowanie obiektowe w Javie cd. Płock, 16 października 2013 r. Programowanie w Javie 1 Wykład i Ćwiczenia 3 Programowanie obiektowe w Javie cd. Płock, 16 października 2013 r. Programowanie obiektowe Programowanie obiektowe (z ang. object-oriented programming), to

Bardziej szczegółowo

Java Język programowania

Java Język programowania Java Język programowania Język Java Bazuje i jest zbliżony do C/C++ Porosty zbiór typów danych (podział na typy prymitywne i obiektowe) Zarządzanie pamięcią i Garbage Collection Zintegrowana synchronizacja

Bardziej szczegółowo

Wstęp do programowania obiektowego. Wykład 2

Wstęp do programowania obiektowego. Wykład 2 Wstęp do programowania obiektowego Wykład 2 1 CECHY I KONCEPCJA PROGRAMOWANIA OBIEKTOWEGO 2 Cechy programowania obiektowego Dla wielu problemów podejście obiektowe jest zgodne z rzeczywistością (łatwe

Bardziej szczegółowo

Konstruktor kopiujacy

Konstruktor kopiujacy Konstruktor kopiujacy Bogdan Kreczmer ZPCiR IIAiR PWr pokój 307 budynek C3 bogdan.kreczmer@pwr.wroc.pl Niniejszy dokument zawiera materiały do wykładu na temat programowania obiektowego. Jest on udostępniony

Bardziej szczegółowo

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów Operatory są elementami języka C++. Istnieje zasada, że z elementami języka, takimi jak np. słowa kluczowe, nie można dokonywać żadnych zmian, przeciążeń, itp. PRZECIĄŻANIE OPERATORÓW Ale dla operatorów

Bardziej szczegółowo

dr inż. Jarosław Forenc

dr inż. Jarosław Forenc Informatyka 2 Politechnika Białostocka - Wydział Elektryczny Elektrotechnika, semestr III, studia niestacjonarne I stopnia Rok akademicki 2012/2013 Wykład nr 6 (07.12.2012) dr inż. Jarosław Forenc Rok

Bardziej szczegółowo

Program 6. Program wykorzystujący strukturę osoba o polach: imię, nazwisko, wiek. W programie wykorzystane są dwie funkcje:

Program 6. Program wykorzystujący strukturę osoba o polach: imię, nazwisko, wiek. W programie wykorzystane są dwie funkcje: Program 6 Program wykorzystujący strukturę osoba o polach: imię, nazwisko, wiek. W programie wykorzystane są dwie funkcje: Funkcja pobierz_osobe wczytuje dane osoby podanej jako argument. Funkcja wypisz_osobe

Bardziej szczegółowo

Podstawy programowania w języku C++ Zadania - dziedziczenie i polimorfizm

Podstawy programowania w języku C++ Zadania - dziedziczenie i polimorfizm Podstawy programowania w języku C++ Zadania - dziedziczenie i polimorfizm Mirosław Głowacki 1,2 1 Akademia Górniczo-Hutnicza im. Stanisława Staszica w Ktrakowie Wydział Inżynierii Metali i Informatyki

Bardziej szczegółowo

Dziedziczenie. dr Jarosław Skaruz

Dziedziczenie. dr Jarosław Skaruz Dziedziczenie dr Jarosław Skaruz http://jareks.ii.uph.edu.pl jaroslaw@skaruz.com Dziedziczenie specjalizacja Dziedziczenie generalizacja Generalizacja-specjalizacja jest takim związkiem pomiędzy klasami,

Bardziej szczegółowo

Programowanie, część I

Programowanie, część I 11 marca 2010 Kontakt Wstęp Informacje organizacyjne Materiał na ćwiczenia Plan wykładu http://www.fuw.edu.pl/~rwys/prog rwys@fuw.edu.pl tel. 22 55 32 263 Materiał na ćwiczenia Informacje organizacyjne

Bardziej szczegółowo

Wprowadzenie do szablonów szablony funkcji

Wprowadzenie do szablonów szablony funkcji Bogdan Kreczmer ZPCiR IIAiR PWr pokój 307 budynek C3 bogdan.kreczmer@pwr.wroc.pl Copyright c 2006 2010 Bogdan Kreczmer Niniejszy dokument zawiera materiały do wykładu na temat programowania obiektowego.

Bardziej szczegółowo

Każdy z nich posiada swoje parametry. W przypadku silnika może to być moc lub pojemność, w przypadku skrzyni biegów można mówić o skrzyni

Każdy z nich posiada swoje parametry. W przypadku silnika może to być moc lub pojemność, w przypadku skrzyni biegów można mówić o skrzyni Język obiektowy był krokiem ewolucji w programowaniu komputerów. Powstał w wyniku rozwoju języków strukturalnych i zmiany podejścia do problemów informatycznych. Cały otaczający świat składa się z obiektów.

Bardziej szczegółowo

Podstawy Programowania semestr drugi. Wykład czternasty

Podstawy Programowania semestr drugi. Wykład czternasty Wykład czternasty 1. Polimorfizm Ostatni wykład zakończyliśmy stwierdzeniem, że możemy obiektowi dowolnej klasy przypisa ć obiekt klasy dziedziczącej po tej klasie. Przypisanie takie obejmuje jednak jedynie

Bardziej szczegółowo