Programozás II gyakorlat. 6. Polimorfizmus



Hasonló dokumentumok
C++ programozási nyelv

3. Osztályok II. Programozás II

Programozás alapjai II. (9. ea) C++ többszörös öröklés, cast, perzisztencia

Bevezetés a C++ programozási nyelvbe

Számítógép és programozás 2

Programozás II. 4. Dr. Iványi Péter

OAF Gregorics Tibor: Minta dokumentáció a 3. házi feladathoz 1.

Virtuális függvények (late binding)

Programozás II gyakorlat. 4. Öröklődés

ISA szimulátor objektum-orientált modell (C++)

Programozás alapjai C nyelv 5. gyakorlat. Írjunk ki fordítva! Írjunk ki fordítva! (3)

Programozás II gyakorlat. 7. Példák a polimorfizmus alkalmazásaira

Osztály és objektum fogalma

Programozás. C++ osztályok. Fodor Attila. Pannon Egyetem Műszaki Informatikai Kar Villamosmérnöki és Információs Rendszerek Tanszék

4. Öröklődés. Programozás II

Objektumelvű alkalmazások fejlesztése 6. gyakorlat. Öröklődés, polimorfizmus. Öröklődés Kódismétlődés objektum-orientált szerkezetben

Bevezetés a Programozásba II 8. előadás. Polimorfizmus Giachetta Roberto

1. Alapok. Programozás II

- 1 - Konstansok használata. Döntsük el, van-e fordítási idejű hiba az alábbi programrészletekben! a) const char * str="zh"; str[0]++;

Programozás C++ -ban

STL gyakorlat C++ Izsó Tamás május 9. Izsó Tamás STL gyakorlat/ 1

Programozás II. ATM példa Dr. Iványi Péter

Programozás alapjai II. (9. ea) C++ többszörös öröklés, cast, perzisztencia

Számítástechnika II. BMEKOKAA Előadás. Dr. Bécsi Tamás

Bevezetés a programozásba Előadás: Objektumszintű és osztályszintű elemek, hibakezelés

Tartalom DCOM. Történeti áttekintés. Történeti áttekintés. Történeti áttekintés. Történeti áttekintés

Öröklés és Polimorfizmus

C# nyelv alapjai. Krizsán Zoltán 1. Objektumorientált programozás C# alapokon tananyag. Általános Informatikai Tanszék Miskolci Egyetem

Maximum kiválasztás tömbben

Pelda öröklődésre: import java.io.*; import java.text.*; import java.util.*; import extra.*;

117. AA Megoldó Alfréd AA 117.

Bevezetés a programozásba előadás: Öröklődés

5. Gyakorlat. struct diak {

Programozás II gyakorlat. 8. Operátor túlterhelés

Bevezetés a programozásba Előadás: A const

Felhasználó által definiált adattípus

C++ programozási nyelv Konstruktorok-destruktorok

Visual C++ osztály készítése, adattagok, és metódusok, láthatóság, konstruktor, destruktor. Objektum létrehozása, használata, öröklés.

Objektumorientált programozás C# nyelven

1. Template (sablon) 1.1. Függvénysablon Függvénysablon példányosítás Osztálysablon

OBJEKTUM ORIENTÁLT PROGRAMOZÁS JAVA NYELVEN. vizsgatételek

Statikus adattagok. Statikus adattag inicializálása. Speciális adattagok és tagfüggvények. Általános Informatikai Tanszék

Objektumok inicializálása

C programozási nyelv Pointerek, tömbök, pointer aritmetika

Globális operátor overloading

Programozási nyelvek Java

Programozási Nyelvek: C++

Pénzügyi algoritmusok

Osztályok. construct () destruct() $b=new Book(); $b=null; unset ($b); book.php: <?php class Book { private $isbn; public $title;

Java programozási nyelv 5. rész Osztályok III.

osztályok kapcsolata Származtatatás C++ Izsó Tamás március 19. Izsó Tamás Származtatatás/ 1

Elemi Alkalmazások Fejlesztése II.

A C++ szigorúbban kezeli a típuseltéréseket, mint a C nyelv Lehetséges típuskonverziók:

Kivételek, kivételkezelés a C++ nyelvben

A C programozási nyelv V. Struktúra Dinamikus memóriakezelés

Programozási nyelvek Java

Abstract osztályok és interface-ek. 7-dik gyakorlat

/* Az iter függvény meghívása és a visszatérő érték átadása a gyok változóba */ gyok = iter( n, a, e ) ;

C memóriakezelés. Mutató típusú változót egy típus és a változó neve elé írt csillag karakterrel hozhatjuk létre.

Programozási nyelvek Java

500. AA Megoldó Alfréd AA 500.

Programozás alapjai II. (4. ea) C++

OOP: Java 8.Gy: Abstract osztályok, interfészek

C++ programozási nyelv

Pénzügyi algoritmusok

és az instanceof operátor

Bevezetés a C++ programozási nyelvbe

Java VIII. Az interfacei. és az instanceof operátor. Az interfészről általában. Interfészek JAVA-ban. Krizsán Zoltán

Bevezetés a Python programozási nyelvbe

Programozás C++ -ban 2007/4

Programozás C++ -ban

Programozás alapjai II. (2. ea) C++

Programozás alapjai II. (2. ea) C++

Programozás. Osztályok, Származtatott osztályok. Fodor Attila

Bánsághi Anna

Objektum Orientált Programozás. 11. Kivételkezelés 44/1B IT MAN

Az alábbi példában a Foo f(5); konstruktor hívása után mennyi lesz f.b értéke? struct Foo { int a, b; Foo(int c):a(c*2),b(c*3) {} };

Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban

A szemantikus elemzés helye. A szemantikus elemzés feladatai. A szemantikus elemzés feladatai. Deklarációk és láthatósági szabályok

Memóriakezelés, dinamikus memóriakezelés

C++ referencia. Izsó Tamás február 17. A C++ nyelvben nagyon sok félreértés van a referenciával kapcsolatban. A Legyakoribb hibák:

Programozás II. 2. Dr. Iványi Péter

Dr. Pál László, Sapientia EMTE, Csíkszereda WEB PROGRAMOZÁS 2.ELŐADÁS. Objektumorientált programozás

JAVA PROGRAMOZÁS 3.ELŐADÁS

500. CC Megoldó Alfréd CC 500.

Bevezetés a programozásba I 10. gyakorlat. C++: alprogramok deklarációja és paraméterátadása

A C# programozási nyelv alapjai

Osztályok. 4. gyakorlat

Java programozási nyelv 4. rész Osztályok II.

Programozás I. gyakorlat

Kivételkezelés, beágyazott osztályok. Nyolcadik gyakorlat

Kivételkezelés a C++ nyelvben Bevezetés

Objektum elvű alkalmazások fejlesztése Kifejezés lengyel formára hozása és kiértékelése

Programozás C++ -ban 2007/7

1. Öröklés Rétegelés Nyilvános öröklés - isa reláció Korlátozó öröklődés - has-a reláció

C++ programozási nyelv Struktúrák a C++ nyelvben

8. gyakorlat Pointerek, dinamikus memóriakezelés

PHP II. WEB technológiák. Tóth Zsolt. Miskolci Egyetem. Tóth Zsolt (Miskolci Egyetem) PHP II / 19

Programozás BMEKOKAA146. Dr. Bécsi Tamás 7. előadás

Átírás:

Programozás II gyakorlat 6. Polimorfizmus

Típuskonverziók C-ben: void * ptr; int * ptr_i = (int*)ptr; Ez működik C++-ban is. Használjuk inkább ezt: int * ptr_i = static_cast<int*>(ptr); Csak egymással kompatibilis mutatókat alakít át! 2

Típuskonverziók const levágása: const char * ptr; char * ptr_c = (char*)ptr; Helyette: char * ptr_c = const_cast<char*>(ptr); 3

Típuskonverziók Konvertálás bármely mutató típus között: char * ptr_c = reinterpret_cast<char*>(0xff2301ab); CHajo * h = reinterpret_cast<chajo*>(0xff2301ab); CRepulo * r = reinterpret_cast<crepulo*>(str); A const eltávolítására nem alkalmas. Figyelem! Csak különleges helyzetekben indokolt a használata! (A kurzus során ilyen helyzet nem áll elő.) 4

Mit ír ki? class Jarmu { int sebesseg; public: void Beolvas() { cout<<"sebesseg: "<<endl; cin>>sebesseg; ; class Repulo: public Jarmu { int magassag; public: void Beolvas() { Jarmu::Beolvas(); cout<<"repulesi magassag: "<<endl; cin>>magassag; ; 5

Mit ír ki? class Hajo: public Jarmu { int vizkisz; public: void Beolvas() { Jarmu::Beolvas(); cout<<"vizkiszoritas: "<<endl; cin>>vizkisz; ; void beolvas(jarmu * j) { j->beolvas(); int main() { Hajo h; beolvas( &h ); 6

Korai kötés Probléma: a beolvas függvény nem tudja, hogy a mutató, amit kap, az Hajo típusú objektumra mutat. Ha a mutato Jarmu típusú, akkor a Jarmu Beolvas függvénye hívódik meg. Korai kötés: Már fordításkor eldől, hogy a függvényhívás helyén pontosan melyik függvény kerül meghívásra. 7

Megoldások Valahogy tudassuk a beolvas függvénnyel, hogy a kapott mutató valójában milyen típusú objektumra mutat! 8

Típusmező enum jarmutipus {JARMU, HAJO, REPULO; class Jarmu { int sebesseg; protected: jarmutipus t; public: Jarmu(jarmutipus t = JARMU) { this->t = t; jarmutipus GetTipus() { return t; [ ] ; 9

Típusmező class Repulo: public Jarmu { int magassag; public: Repulo(): Jarmu(REPULO) { [...] ; class Hajo: public Jarmu { int vizkisz; public: Hajo(): Jarmu(HAJO) { [...] ; 10

Típusmező void beolvas(jarmu * j) { switch (j->gettipus()) { case JARMU: j->beolvas(); break; case HAJO: static_cast<hajo*>(j)->beolvas(); break; case REPULO: static_cast<repulo*>(j)->beolvas(); 11

Típusmező Probléma: Sok származtatott osztálynál nehézzé válik, nagy a figyelmetlenségből fakadó hiba veszélye. Nem automatikus. Lehetőleg ne használjunk típusmezőt! 12

Virtuális függvények Az előzőekben mi helyeztük el a típusra utaló információt az osztályba. Ez automatizálható, tegyük virtuálissá az ősosztály Beolvas függvényét! class Jarmu { int sebesseg; public: virtual void Beolvas() { cout<<"sebesseg: "<<endl; cin>>sebesseg; ; 13

Virtuális függvénytáblák Jarmu Függvény neve Beolvas() Függvény címe Jarmu::Beolvas() Hajo Függvény neve Beolvas() Függvény címe Hajo::Beolvas() Jarmu j; Hajo h; Virtuális függvénytábla címe Virtuális függvénytábla címe 14

Virtuális függvénytáblák Jarmu Függvény neve Beolvas() Függvény címe Jarmu::Beolvas() Hajo Függvény neve Beolvas() Függvény címe Hajo::Beolvas() Jarmu j; Hajo h; Virtuális függvénytábla címe Virtuális függvénytábla címe 14

Polimorfizmus void beolvas(cjarmu * j) { j->beolvas(); int main() { Hajo h; Repulo r; beolvas( &h ); beolvas( &r ); Beolvas() virtuális? igen Melyik virtuális függvénytáblára hivatkozik? A táblából kikeressük a függvényt, és meghívjuk 15

dynamic_cast Futás időben lekérdezhetjük, hogy egy adott objektum egy meghatározott típusba esik-e. A vizsgálathoz a virtualitást használja fel. NULL pointerrel tér vissza, ha a megadott mutató nem olyan típusú objektumra mutat, mint amilyent megadtunk neki. Csak virtuális függvényeket tartalmazó osztályoknál használható! 16

dynamic_cast void beolvas(jarmu * j) { if (Hajo * h = dynamic_cast<hajo*>(j)) h->beolvas(); if (Repulo * r = dynamic_cast<repulo*>(j)) r->beolvas(); 17

dynamic_cast void beolvas(jarmu * j) { if (Hajo * h = dynamic_cast<hajo*>(j)) h->beolvas(); if (Repulo * r = dynamic_cast<repulo*>(j)) r->beolvas(); A j mutató Hajo-ra mutat? A j mutató Repulo-re mutat? 17

dynamic_cast Referenciára is alkalmazható, ám sikertelen konvertálás után bad_cast (typeinfo header-ben) kivételt dob (referencia nem lehet NULL értékű, mint a mutatók). 18

dynamic_cast #include <typeinfo> void beolvas(jarmu & j) { try { Hajo & h = dynamic_cast<hajo&>(j); h.beolvas(); catch (bad_cast & bc) { cout<<"ez nem hajo"<<endl; try { Repulo & r = dynamic_cast<repulo&>(j); r.beolvas(); catch (bad_cast & bc) { cout<<"ez nem repulo"<<endl; 19

dynamic_cast A dynamic_cast lassabb, mint a típusmező használata. A dynamic_cast alkalmazásakor nem kell a típusmezővel bajlódni, így annál egyszerűbb. Csak indokolt esetben használjuk, legtöbb esetben felesleges. 20

Tisztán virtuális függvények Ne példányosíthassuk a Jarmu osztályt A virtuális függvény deklarációjának végére = 0 t írunk: class Jarmu { protected: int sebesseg; public: virtual void Beolvas() = 0; ; 21

Tisztán virtuális függvények A Jarmu osztály most absztrakt osztály: Nem lehet példányosítani Arra való, hogy egy interface-t adjunk meg vele A belőle származtatott osztályokban, ha azokat példányosítani akarjuk, definiálni kell a tisztán virtuális (pure virtual) függvényeket 22

Tisztán virtuális függvények Figyelem! A származtatott osztályokból nem hívhatjuk meg a szülő pure virtuális függvényeit! class Repulo: public Jarmu { int magassag; public: void Beolvas() { Jarmu::Beolvas(); cout<<"repulesi magassag: "<<endl; cin>>magassag; 23

Feladat Deklarálj egy 5 elemű, Jarmu * típusú tömböt! Írj programot, amely megkérdezi, hogy az i. elem a tömbben hajó, vagy repülő, a választásnak megfelelően dinamikusan lefoglalja az objektumot, majd egy külön a beker függvény segítségével beolvassa a tömb elemeinek adatait! (A beker használja az osztályok Beolvas függvényét) A végén szabadítsd fel az elemeket! 26

Megoldás int main() { Jarmu * jarmuvek[5]; int i; for (i = 0; i < 5; i++) { char ch; cout<<"tipus (h / r): "; cin>>ch; switch (ch) { case 'r': jarmuvek[i] = new Repulo; break; case 'h': jarmuvek[i] = new Hajo; break; beker(jarmuvek, 5); for (i = 0; i < 5; i++) delete jarmuvek[i]; 27

Megoldás void beker(jarmu ** j, int mennyi) { for (int i = 0; i < mennyi; i++){ cout<<i+1<<". jarmu: "<<endl; j[i]->beolvas(); 28

Házi feladat Írj sakk programot! Egy 8*8-as táblán helyezkedjenek el a bábuk, a cellák típusa Babu* legyen. A sakk szabályainak megfelelően származtass belőle különböző bábú típusokat. A program két emberi játékos közötti sakk játszmát bonyolítson le. Először a fehér, majd a fekete játékos lép. A program mindig olvassa be, hogy az aktuális játékos melyik bábujával akar lépni. 29

Házi feladat A programnak ellenőriznie kell, hogy a kiválasztott bábu meglépheti-e azt a lépést, amit a játékos választott. A Babu osztálynak legyen tehát egy függvénye, amely ellenőrzi a lépésről, hogy az megengedett-e az adott bábu számára. Például a bástya csak egyenesen léphet, de akármennyit. Ha ferdén próbálunk lépni, akkor a függvény hamis értékkel tér vissza. Ennek a függvénynek nem kell ellenőriznie, hogy más áll-e az adott mezőn, ezt kezelje a főprogram. 30

Házi feladat A program minden lépés után kirajzolja a képernyőre a sakktáblát, rajta a bábukkal. Az egyes bábukat betűkkel jelöld. A kirajzolás során a bábu objektumok maguk írják ki a jelüket a képernyőre egy saját tagfüggvénnyel. A kirajzolás során legyenek megkülönböztethetőek a fekete és fehér bábuk A bábuk tudják, hogy milyen színűek, és hogy mely pozíción találhatóak. 31

Házi feladat A játszma addig tart, amíg az egyik játékos mattot nem kap, vagy az egyik játékos fel nem adja. Nem kötelező a teljes sakk szabályzatot implementálni. Amit tudnia kell a programnak: Különböző bábuk különböző módon léphetnek (http://hu.wikipedia.org/wiki/sakk) Nem szükséges belerakni a különleges lépéseket Tervezd meg, hogy milyen további segéd függvényekkel kell rendelkeznie a bábu osztályoknak 32