Alkalmazott modul: Programozás 11. előadás. Objektumorientált programozás: öröklődés

Hasonló dokumentumok
Szoftvertechnológia 4. előadás. Objektumorientált tervezés: általánosítás. Giachetta Roberto. Eötvös Loránd Tudományegyetem Informatikai Kar

Informatikai Kar. 4. fejezet. Giachetta Roberto

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

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

Alkalmazott Modul III 6. előadás. Objektumorientált programozás: öröklődés és polimorfizmus

Objektumorientált programozás C# nyelven

Java VI. Miskolci Egyetem Általános Informatikai Tanszék. Utolsó módosítás: Ficsor Lajos. Java VI.: Öröklődés JAVA6 / 1

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

Öröklés és Polimorfizmus

Bevezetés a Programozásba II 5. előadás. Objektumorientált programozás és tervezés

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

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

C++ programozási nyelv

Alkalmazott modul: Programozás 10. előadás. Objektumorientált programozás: tervezés és megvalósítás

Osztályok. 4. gyakorlat

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

Programozási nyelvek Java

Programozási technológia

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

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.

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

Objektumorientált programozás C# nyelven

Bevezetés a Programozásba II 2. előadás. Adattípusok megvalósítása egységbe zárással. Adattípusok megvalósítása egységbe zárással

Programozás módszertan p.1/46

Java VI. Egy kis kitérő: az UML. Osztály diagram. Általános Informatikai Tanszék Utolsó módosítás:

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

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

Programozás I. 5. gyakorlat. Szegedi Tudományegyetem Természettudományi és Informatikai Kar

Programozási nyelvek Java

Bevezetés a Programozásba II 3. előadás. Biztonságos adattípusok megvalósítása

JAVA PROGRAMOZÁS 2.ELŐADÁS

Bevezetés a Programozásba II 3. előadás. Biztonságos adattípusok megvalósítása. Biztonságos adattípusok megvalósítása

Széchenyi István Egyetem. Programozás III. Varjasi Norbert

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

Interfészek. PPT 2007/2008 tavasz.

Programozás II. 2. gyakorlat Áttérés C-ről C++-ra

Bevezetés a Programozásba II 11. előadás. Adatszerkezetek megvalósítása. Adatszerkezetek megvalósítása Adatszerkezetek

és az instanceof operátor

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

Alkalmazott Modul III 6. gyakorlat. Objektumorientált programozás: öröklődés és polimorfizmus

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

Már megismert fogalmak áttekintése

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

OOP #14 (referencia-elv)

Java VII. Polimorfizmus a Java nyelvben

Objektumelvű programozás

Java VII. Polimorfizmus a Java nyelvben

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

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

3. Osztályok II. Programozás II

Programozás II gyakorlat. 6. Polimorfizmus

C++ programozási nyelv Konstruktorok-destruktorok

Interfészek. Programozás II. előadás. Szénási Sándor.

Programozási alapismeretek 4.

Miután létrehoztuk, szeretnénk neki beszédesebb nevet adni. A név változtatásához a következőt kell tenni:

Osztály és objektum fogalma

Osztály öröklődés. Öröklődés és polimorfizmus. Programozás II. előadás. Szénási Sándor.

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

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

Elemi Alkalmazások Fejlesztése II.

Objektumok inicializálása

Objektumorientált Programozás C++ ADATSZERKEZETEK ÉS ALGORITMUSOK 2. GYAKORLAT

Bevezetés a Python programozási nyelvbe

Eseményvezérelt alkalmazások fejlesztése I 11. előadás. Szoftverek tesztelése

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

C++ programozási nyelv

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

JAVA PROGRAMOZÁS 3.ELŐADÁS

Bevezetés a programozásba Előadás: Tagfüggvények, osztály, objektum

Programozási nyelvek Java

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

Szoftvertechnológia 3. előadás. Objektumorientált tervezés: alapismeretek. Giachetta Roberto. Eötvös Loránd Tudományegyetem Informatikai Kar

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

Programozás. Objektum Orientált Programozás (OOP) Alapfogalmak. Fodor Attila

Bánsághi Anna 2014 Bánsághi Anna 1 of 33

Helyes-e az alábbi kódrészlet? int i = 1; i = i * 3 + 1; int j; j = i + 1; Nem. Igen. Hányféleképpen lehet Javaban megjegyzést írni?

Java és web programozás

1. Mi a fejállományok szerepe C és C++ nyelvben és hogyan használjuk őket? 2. Milyen alapvető változókat használhatunk a C és C++ nyelvben?

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

Származtatási mechanizmus a C++ nyelvben

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

OOP. Alapelvek Elek Tibor

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

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

Objektumorientált szoftverfejlesztés alapjai

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

Programozás C++ -ban

Web-technológia PHP-vel

Java III. I I. Osztálydefiníció (Bevezetés)

Bevezetés, a C++ osztályok. Pere László

Bánsághi Anna 2014 Bánsághi Anna 1 of 68

Java III. I I. Osztálydefiníció (Bevezetés)

Java V. Osztályszint. lyszintű ű tagok. Példányváltozó. Osztályváltozó. Általános Informatikai Tanszék Utolsó módosítás:

Programozás C++ -ban 2007/7

Objektumorientált programozás C# nyelven II.

Programozás C++ -ban

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) {} };

Informatikai Kar. 3. fejezet. alapismeretek. Giachetta Roberto

Alkalmazott modul: Programozás 10. fejezet. Strukturált programozás: dinamikus memóriakezelés. Giachetta Roberto

Átírás:

Eötvös Loránd Tudományegyetem Informatikai Kar Alkalmazott modul: Programozás 11. előadás Objektumorientált programozás: öröklődés Giachetta Roberto groberto@inf.elte.hu http://people.inf.elte.hu/groberto

Példa Feladat: Készítsünk egy programot, amelyben különböző geometriai alakzatokat hozhatunk létre (háromszög, négyzet, téglalap, szabályos hatszög), és lekérdezhetjük a területüket, illetve kerületüket. a négy alakzatot négy osztály segítségével ábrázoljuk (Triangle, Square, Rectangle, Hexagon) a háromszöget, négyzetet, hatszöget egy egész számmal reprezentáljuk (_a), a téglalapot két számmal (_a, _b) mindegyik osztálynak biztosítunk lekérdező műveleteket a területre (area) és a kerületre (perimeter) ELTE IK, Alkalmazott modul: Programozás 11:2

Példa Tervezés: - _a :int Hexagon + Hexagon(int) + area() :double {query} + perimeter() :int {query} - _a :int - _b :int Rectangle + Rectangle(int, int) + area() :int {query} + perimeter() :int {query} - _a :int Triangle + Triangle(int) + area() :double {query} + perimeter() :int {query} - _a :int Square + Square(int) + area() :int {query} + perimeter() :int {query} ELTE IK, Alkalmazott modul: Programozás 11:3

Kódismétlődés objektum-orientált szerkezetben Az objektum-orientált programokban a különböző osztályok felépítése, viselkedése megegyezhet ez kódismétlődéshez vezet, és rontja a kódminőséget Hasonlóan procedurális programozás esetén is előfordulhat kódismétlődés, amely alprogramok bevezetésével kiküszöbölhető objektumorientált programok esetén a működés szorosan összekötött az adatokkal így csak együttesen emelhetőek ki, létrehozva ezzel egy új, általánosabb osztályt, amelyet össze kell kapcsolnunk a jelenlegi, speciálisabb osztállyal ELTE IK, Alkalmazott modul: Programozás 11:4

Általánosítás és specializáció Pl.: egyetemi polgár van azonosítója, bejár az egyetemre speciálisabb hallgató oktató kutató tárgyai vannak, vizsgázik kurzusokat tart, vizsgáztat kutatást végez, cikkeket ír ELTE IK, Alkalmazott modul: Programozás 11:5

Általánosítás és specializáció Pl.: általánosabb ember egyetemi polgár hallgató matematikus tanul, van neve speciálisabb bejár az egyetemre, van azonosítója vizsgázik, vannak tárgyai n dimenzióban gondolkozik ELTE IK, Alkalmazott modul: Programozás 11:6

Általánosítás és specializáció Az általánosabb, illetve speciálisabb osztályok között fennálló kapcsolatot nevezzük általánosításnak (generalization) <általános> <speciális> a speciális átveszi az általános összes jellemzőjét (tagok, kapcsolatok), amelyeket tetszőlegesen kibővíthet, vagy újrafogalmazhat az ellentétes irányú relációt nevezzük specializációnak (specialization) az általános osztályt ősnek (base, superclass), a speciális osztályt leszármazottnak (descendant, subclass) nevezzük ELTE IK, Alkalmazott modul: Programozás 11:7

Megvalósítása Az általánosítást a programozási nyelvekben az öröklődés (inheritance) technikájával valósítjuk meg, amely lehet specifikációs: csak az általános absztrakt jellemezőit (interfészét) veszi át a speciális implementációs: az osztály absztrakt és konkrét jellemzőit (interfészét és implementációját) veszi át a speciális Öröklődés C++ nyelven: class <osztálynév> : <láthatóság> <ősosztály> { <kiegészítések> }; ELTE IK, Alkalmazott modul: Programozás 11:8

Megvalósítása Pl.: class Superclass // általános osztály { public: int value; // mező Superclass() { value = 1; } // konstruktor void setvalue(int v) { value = v; } int getvalue() { return value; } // metódusok }; Superclass super; // osztály példányosítása cout << super.value; // 1 super.setvalue(5); cout << super.value; // 5 ELTE IK, Alkalmazott modul: Programozás 11:9

Megvalósítása Pl.: class Subclass : public Superclass // speciális osztály, amely megkapja a value, // setvalue(int), getvalue() tagokat { public: int othervalue; Subclass() { value = 2; // használhatjuk az örökölt mezőt othervalue = 3; } void setothervalue(int v) { othervalue = v; } int getothervalue() { return othervalue; } }; ELTE IK, Alkalmazott modul: Programozás 11:10

Megvalósítása Pl.: Subclass sub; // leszármazott példányosítása // elérhetjük az örökölt tagokat: cout << sub.value; // 2 sub.setvalue(5); cout << sub.value; // 5 // elérhetjük az új tagokat: cout << sub.othervalue; // 3 sub.setothervalue(4); cout << sub.getothervalue(); // 4 ELTE IK, Alkalmazott modul: Programozás 11:11

Láthatóság A tagok láthatósága az öröklődés során is szerepet játszik a látható (public) tagok elérhetőek lesznek a leszármazottban, a rejtett (private) tagok azonban közvetlenül nem ugyanakkor a rejtett tagok is öröklődnek, és közvetetten (örökölt látható műveleteken keresztül) elérhetőek sokszor hasznos, ha a leszármazott osztály közvetlenül elérheti a rejtett tartalmat, ezért bevezetünk egy harmadik, védett (protected) láthatóságot az osztályban és leszármazottaiban látható, kívül nem az osztálydiagramban # jelöli ELTE IK, Alkalmazott modul: Programozás 11:12

Láthatóság Pl.: class Superclass { private: int value; // rejtett mező public: Superclass() { value = 1; } void setvalue(int v) { value = v; } int getvalue() { return value; } }; Superclass super; cout << super.getvalue(); // 1 super.setvalue(5); cout << super.getvalue(); // 5 ELTE IK, Alkalmazott modul: Programozás 11:13

Láthatóság Pl.: class Subclass : public Superclass { // a value már nem látszódik, de öröklődik private: int othervalue; public: Subclass() { setvalue(2); // nem látja a value mezőt, de // közvetetten használhatja othervalue = 3; } }; ELTE IK, Alkalmazott modul: Programozás 11:14

Láthatóság Pl.: Subclass sub; // leszármazott példányosítása // elérhetjük az örökölt tagokat: cout << sub.getvalue(); // 2 sub.setvalue(5); cout << sub.getvalue(); // 5 // elérhetjük az új tagokat: cout << sub.getothervalue(); // 3 sub.setothervalue(4); cout << sub.getothervalue(); // 4 ELTE IK, Alkalmazott modul: Programozás 11:15

Láthatóság Pl.: class Superclass { protected: int value; // védett mező public: Superclass() { value = 1; } void setvalue(int v) { value = v; } int getvalue() { return value; } }; Superclass sup; cout << sup.getvalue(); // 1 sup.setvalue(5); cout << sup.getvalue(); // 5 ELTE IK, Alkalmazott modul: Programozás 11:16

Láthatóság Pl.: class Subclass : public Superclass { // minden elérhető lesz az ősből private: int othervalue; public: Subclass() { value = 2; // használhatjuk az örökölt mezőt othervalue = 3; } }; ELTE IK, Alkalmazott modul: Programozás 11:17

Példa Feladat: Készítsünk egy programot, amelyben különböző geometriai alakzatokat hozhatunk létre (háromszög, négyzet, téglalap, szabályos hatszög), és lekérdezhetjük a területüket, illetve kerületüket. javítsunk a korábbi megoldáson öröklődés segítségével kiemelünk egy általános alakzat osztályt (Shape), amelybe helyezzük a közös adatot (_a), ennek védett (protected) láthatóságot adunk a többi osztályban csak az öröklődést jelezzük, a működés nem változik (továbbra is a konstruktorok állítják be _a értékét) ELTE IK, Alkalmazott modul: Programozás 11:18

Példa Tervezés: Shape # _a :int + Shape() Hexagon Rectangle Square Triangle + Hexagon(int) + area() :double {query} + perimeter() :int {query} - _b :int + Rectangle(int, int) + area() :int {query} + perimeter() :int {query} + Square(int) + area() :int {query} + perimeter() :int {query} + Triangle(int) + area() :double {query} + perimeter() :int {query} ELTE IK, Alkalmazott modul: Programozás 11:19

Tagok elrejtése és elérése Öröklődés során lehetőségünk van a viselkedés újrafogalmazására a leszármazottban az ősével megegyező szintaktikájú metódusok elrejtik, vagy felüldefiniálják az örökölt metódusokat lehetőségünk van explicit hivatkozni az ős bármely látható tulajdonságára az <ős osztály>:: előtaggal Pl.: class SuperClass { void getdefaultvalue() { return 1; } }; ELTE IK, Alkalmazott modul: Programozás 11:20

Tulajdonságok elrejtése és elérése class SubClass : public SuperClass { void getdefaultvalue() { return 2; } // elrejtő metódus void getdefaultsupervalue() { return SuperClass::getDefaultValue(); } // ős metódusának meghívása }; SuperClass sup; cout << sup.getdefaultvalue(); // kiírja: 1 SubClass sub; cout << sub.getdefaultvalue(); // kiírja: 2 cout << sub.getdefaultsupervalue(); // kiírja: 1 ELTE IK, Alkalmazott modul: Programozás 11:21

A konstruktor és destruktor öröklődése A konstruktor automatikusan öröklődik a paraméter nélküli konstruktor automatikusan (implicit módon) meghívódik amikor a leszármazottból létrehozunk egy példányt elsőként az ős konstruktora hajtódik végre, azután a leszármazott konstruktora lehetőségünk van az ős konstruktorának explicit meghívására is <osztálynév> <konstruktor> : <ős konstruktornév>(<átadott paraméterek>) formában paraméteres konstruktorokra csak az explicit hívás használható ELTE IK, Alkalmazott modul: Programozás 11:22

Konstruktor és destruktor A destruktor automatikusan öröklődik és minden ős destruktor meghívódik a leszármazott destruktor meghívásakor elsőként a leszármazott, majd az ős destruktora Pl.: class FirstClass { public: FirstClass() { cout << "1 start" << endl; } ~FirstClass() { cout << "1 stop" << endl; } }; class SecondClass : public FirstClass { public: ELTE IK, Alkalmazott modul: Programozás 11:23

Konstruktor és destruktor }; SecondClass() { cout << "2 start" << endl; } ~SecondClass() { cout << "2 stop" << endl; } int main(){ SecondClass second; // konstruktor hívás return 0; } // destruktor hívás /* eredmény: 1 start 2 start 2 stop 1 stop */ ELTE IK, Alkalmazott modul: Programozás 11:24

Példa Feladat: Készítsünk egy programot, amelyben különböző geometriai alakzatokat hozhatunk létre (háromszög, négyzet, téglalap, szabályos hatszög), és lekérdezhetjük a területüket, illetve kerületüket. javítsunk a korábbi megoldáson azzal, hogy az ős (Shape) konstruktorára bízzuk a mező (_a) inicializálását adhatunk az ősben műveleteket a terület és a kerület lekérdezésére, de ezeket a leszármazottban elrejtjük a leszármazott osztályok konstruktorai csak meghívják az ős konstruktorát, és tovább adják a kapott paramétert ELTE IK, Alkalmazott modul: Programozás 11:25

Példa Tervezés: # _a :int Shape + Shape(int) + area() :double {query} + perimeter() :int {query} Hexagon Rectangle Square Triangle + Hexagon(int) + area() :double {query} + perimeter() :int {query} - _b :int + Rectangle(int, int) + area() :int {query} + perimeter() :int {query} + Square(int) + area() :int {query} + perimeter() :int {query} + Triangle(int) + area() :double {query} + perimeter() :int {query} ELTE IK, Alkalmazott modul: Programozás 11:26

Polimorfizmus Mivel a leszármazott példányosításakor egyúttal az ősből is létrehozunk egy példányt, a keletkezett objektum példánya lesz mindkét típusnak a leszármazott objektum bárhova behelyettesíthető lesz, ahol az ős egy példányát használjuk Ezt a jelenséget (altípusos) polimorfizmusnak (polymorphism, subtyping), vagy többalakúságnak nevezzük pl. a Subclass sub; utasítással egyúttal a Superclass példányát is elkészítjük öröklődés nélkül is fennállhat dinamikus típusrendszerű programozási nyelvekben (ez a strukturális polimorfizmus) ELTE IK, Alkalmazott modul: Programozás 11:27

Polimorfizmus A programozási nyelvek az objektumokat általában dinamikusan kezelik (referencián, vagy mutatón keresztül) pl.: Subclass* sub = new Subclass(); cout << sub->getvalue(); // 2 A polimorfizmus lehetővé teszi, hogy a dinamikusan létrehozott objektumra hivatkozzunk az ősosztály segítségével pl.: Superclass* sub = new Subclass(); // a mutató az ősosztályé, de ténylegesen // a leszármazott objektummal dolgozunk cout << sub->getvalue(); // 2 ELTE IK, Alkalmazott modul: Programozás 11:28

Polimorfizmus A dinamikusan létrehozott objektumot így két típussal rendelkeznek: a hivatkozás osztálya az objektum statikus típusa, ezt értelmezi a fordítóprogram, ennek megfelelő tagokat hívhatunk meg a példányosított osztály a változó dinamikus típusa, futás közben az annak megfelelő viselkedést végzi Pl.: Superclass* s1 = new Subclass(); // s1 statikus típusa Superclass, // dinamikus típusa Subclass Superclass* s2 = new Superclass(); // itt egyeznek ELTE IK, Alkalmazott modul: Programozás 11:29

Polimorfizmus A dinamikus típus futás közben változtatható, mivel az ős típusú hivatkozásra tetszőleges leszármazott példányosítható pl.: Superclass* sup = new Superclass(); cout << sup->getvalue(); // 1 delete sup; sup = new Subclass(); cout << sup->getvalue(); // 2 ugyanakkor a statikus típusra korlátozott az elérhető tagok köre, pl.: cout << sup->getothervalue(); // fordítási hiba, a statikus típusnak nincs // getothervalue() művelete ELTE IK, Alkalmazott modul: Programozás 11:30

Polimorfizmus A dinamikus típus műveleteinek elérésére típuskonverziót használhatunk a dynamic_cast<típus>(<mutató>) utasítás segítségével helytelen konverzió esetén NULL mutatót ad vissza pl.: Superclass* sup = new Subclass(); if (dynamic_cast<subclass*>(sup)) { // ha konvertálható az adott típusra Subclass *sub = dynamic_cast<subclass*>(sup); // elvégezzük a konverziót sub->getothervalue(); // így már futtatható a művelet } ELTE IK, Alkalmazott modul: Programozás 11:31

Polimorfizmus A polimorfizmus azt is lehetővé teszi, hogy egy gyűjteményben különböző típusú elemeket tároljunk az gyűjtemény elemtípusa az ős hivatkozása lesz, és az elemek dinamikus típusát tetszőlegesen váltogathatjuk Pl.: Superclass* array[3]; array[0] = new Superclass(); array[1] = new Subclass(); array[2] = new Subclass(); for (int i = 0; i < 3; i++) cout << array[i]->getvalue(); // 1 2 2 ELTE IK, Alkalmazott modul: Programozás 11:32

Dinamikus kötés Dinamikus példányosítást használva a program a dinamikus típusnak megfelelő viselkedést rendeli hozzá az objektumhoz futási idő alatt, ezt dinamikus kötésnek (dynamic binding) nevezzük tehát amennyiben felüldefiniálunk (override) egy műveletet, a dinamikus típusnak megfelelő végrehajtás fog lefutni ehhez azonban a műveletnek engedélyeznie kell a felüldefiniálást, ekkor beszélünk virtuális (virtual) műveletről virtuális műveletet a virtual kulcsszóval hozható létre a konstruktor sohasem lehet virtuális ELTE IK, Alkalmazott modul: Programozás 11:33

Dinamikus kötés Pl.: a nem virtuális műveletek a lezárt, vagy véglegesített (sealed) műveletek lezárt műveletet csak elrejteni lehet, amely esetben a statikus típus szerint hajtódik végre a művelet alapesetben a műveletek lezártak class Superclass { virtual void getvalue() { return value; } // virtuális metódus void getdefaultvalue() { return 1; } // véglegesített metódus }; ELTE IK, Alkalmazott modul: Programozás 11:34

Dinamikus kötés class Subclass : public Superclass { void getvalue() { return othervalue; } // felüldefináló metódus void getdefaultvalue() { return 2; } // elrejtő metódus }; Superclass *sup = new Superclass(); cout << sup->getvalue(); // 1 cout << sup->getdefaultvalue(); // 1 sup = new Subclass(); cout << sup->getvalue(); // 3 cout << sup->getdefaultvalue(); // 1 ELTE IK, Alkalmazott modul: Programozás 11:35

Dinamikus kötés Feladat: Készítsünk egy programot, amelyben különböző geometriai alakzatokat hozhatunk létre (háromszög, négyzet, téglalap, szabályos hatszög), és lekérdezhetjük a területüket, illetve kerületüket. Az alakzatokat csoportosíthatjuk is. az ősben a terület (area), illetve kerület (perimeter) lekérdezés metódusait virtuálissá változtatjuk, így már felüldefiniáljuk őket a leszármazottban létrehozzuk az alakzatok csoportját (Group), amelybe behelyezzük az alakzatok gyűjteményét, polimorfizmus segítségével lekérdezhetjük a csoportba lévő elemek összterületét és összkerületét ELTE IK, Alkalmazott modul: Programozás 11:36

Dinamikus kötés Tervezés: Group - _shapes :vector<shape*> + addshape(shape*) :void + removeshape(shape*) :void + area() :double {query} + perimeter() :int {query} -_shapes * # _a :int Shape + Shape(int) + area() :double {query} + perimeter() :int {query} Hexagon Rectangle Square Triangle + Hexagon(int) + area() :double {query} + perimeter() :int {query} - _b :int + Rectangle(int, int) + area() :int {query} + perimeter() :int {query} + Square(int) + area() :int {query} + perimeter() :int {query} + Triangle(int) + area() :double {query} + perimeter() :int {query} ELTE IK, Alkalmazott modul: Programozás 11:37

Virtuális destruktor A destruktor meghívása a többi metódushoz hasonlóan történik amennyiben véglegesített, akkor a statikus típus szerinti destruktor hívódik meg vagyis előfordulhat, hogy a leszármazott dinamikus típusban létrehozott dinamikus elemek nem törlődnek a memóriából amennyiben virtuális, akkor a dinamikus típus szerinti destruktor hívódik meg célszerű a destruktort minden osztályban virtuálisnak megadni, így az objektumot megsemmisítésével soha nem adódik probléma ELTE IK, Alkalmazott modul: Programozás 11:38

Virtuális destruktor Pl.: class FirstClass { public: FirstClass() { cout << "1 start" << endl; } ~FirstClass() { // véglegesített destruktor cout << "1 stop" << endl; } }; class SecondClass : public FirstClass { public: SecondClass() { cout << "2 start" << endl; } ~SecondClass() { cout << "2 stop" << endl; } }; ELTE IK, Alkalmazott modul: Programozás 11:39

Virtuális destruktor int main(){ FirstClass* first = new SecondClass(); // konstruktor hívás delete first; // destruktor hívás // (a FirstClass destruktorára) return 0; } /* eredmény: 1 start 2 start 1 stop */ ELTE IK, Alkalmazott modul: Programozás 11:40

Virtuális destruktor Pl.: class FirstClass { public: FirstClass() { cout << "1 start" << endl; } virtual ~FirstClass() { // virtuális destruktor cout << "1 stop" << endl; } }; class SecondClass : public FirstClass { public: SecondClass() { cout << "2 start" << endl; } ~SecondClass() { cout << "2 stop" << endl; } }; ELTE IK, Alkalmazott modul: Programozás 11:41

Virtuális destruktor int main(){ FirstClass* first = new SecondClass(); // konstruktor hívás delete first; // destruktor hívás // (a SecondClass destruktorára) return 0; } /* eredmény: 1 start 2 start 2 stop 1 stop */ ELTE IK, Alkalmazott modul: Programozás 11:42

Absztrakt osztályok Amennyiben egy ősosztály olyan általános viselkedéssel rendelkezik, amelyet konkrétan nem tudunk alkalmazni, vagy általánosságban nem tudunk jól definiálni, akkor megtilthatjuk az osztály példányosítását A nem példányosítható osztályt absztrakt osztálynak (abstract class) nevezzük a diagramban dőlt betűvel jelöljük csak statikus típusként szerepelhetnek absztrakt osztályban létrehozható olyan művelet, amelynek nincs megvalósítása, csak szintaxisa (ezt =0 jelöli), ezek az absztrakt, vagy tisztán virtuális műveletek ELTE IK, Alkalmazott modul: Programozás 11:43

Absztrakt osztályok Pl.: a leszármazottak megvalósítják (realize) az absztrakt műveletet (vagy szintén absztrakt osztályok lesznek) absztrakt osztály létrehozható a konstruktor elrejtésével, vagy absztrakt művelet definiálásával class Superclass { // absztrakt osztály virtual void getvalue() =0; // absztrakt metódus }; Superclass *sup = new Subclass(); cout << sup.getvalue(); // 3 sup = new Superclass(); // fordítási hiba ELTE IK, Alkalmazott modul: Programozás 11:44

Példa Feladat: Készítsünk egy programot, amelyben egyetemi oktatók, hallgatók és kurzusok adatait tudjuk tárolni. a hallgató (UniversityStudent) és az oktató (UniversityTeacher) közös tagjait kiemeljük az egyetemi polgár (UniversityCitizen) absztrakt ősosztályba a leszármazottak definiálják a newcourse( ) műveletet külön-külön, ezért az ősben tisztán absztrakt lesz, továbbá a hallgatónál megjelenik a kreditek lekérdezése (numberofcredits()) a változtatás a kurzus (Course) osztályra nincs hatással ELTE IK, Alkalmazott modul: Programozás 11:45

Példa Tervezés: UniversityCitizen # _name :std::string # _neptuncode :std::string # _neptunpassword :std::string # _courses :std::vector<course*> + ~UniversityCitizen() + name() :std::string {query} + neptuncode() :std::string {query} + courses() :std::vector<course*> {query} + numberofcourses() :int {query} + newcourse(course*) :void # UniversityCitizen(std::string&) - generatecode() :std::string - generatepassword() :std::string UniversityStudent + UniversityStudent(std::string&) + ~UniversityStudent() + numberofcredits() :int {query} + newcourse(course*) :void -_students * UniversityTeacher + UniversityTeacher(std::string&) + ~UniversityTeacher() + newcourse(course*) :void -_teacher -_courses * Course - _coursename :std::string - _teacher :UniversityTeacher* - _credits :int - _maxheadcount :unsigned int - _students :std::vector<const UniversityStudent*> + Course(std::string&, UniversityTeacher*, int, unsigned int) + newstudent(universitystudent*) :bool + name() :std::string {query} + teacher() :UniversityTeacher* {query} + credits() :int {query} + maxheadcount() :int {query} + currentheadcount() :int {query} ELTE IK, Alkalmazott modul: Programozás 11:46

Példa Megoldás (universitystudent.hpp): class UniversityStudent : public UniversityCitizen { // hallgató osztálya, speciális egyetemi polgár public: UniversityStudent(const std::string& n); ~UniversityStudent(){} int numberofcredits() const; }; void newcourse(course* c); ELTE IK, Alkalmazott modul: Programozás 11:47

Példa Megoldás (main.cpp): UniversityTeacher groberto("giachetta Roberto"); vector<universitycitizen*> citizens; citizens.push_back(&groberto); // polimorfizmust használunk cout << "Az egyetem polgárai: " << endl; for (int i = 0; i < citizens.size(); i++){ cout << citizens[i]->name() << ", NEPTUN: " << citizens[i]->neptuncode() << endl; } ELTE IK, Alkalmazott modul: Programozás 11:48