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

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

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

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

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

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

Programozás C++ -ban 2007/4

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

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

Programozás II gyakorlat. 6. Polimorfizmus

Programozás C++ -ban

Osztály és objektum fogalma

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

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

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

Objektumok inicializálása

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

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

117. AA Megoldó Alfréd AA 117.

Programozási nyelvek Java

Globális operátor overloading

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

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

C++ programozási nyelv Konstruktorok-destruktorok

500. AA Megoldó Alfréd AA 500.

Osztályok. 4. gyakorlat

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

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

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.

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

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

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

3. Osztályok II. Programozás II

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

Objektumorientált programozás C# nyelven

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

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

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

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

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

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

500. CC Megoldó Alfréd CC 500.

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

Származtatási mechanizmus a C++ nyelvben

Programozás C++ -ban 2007/7

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

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

OOP #14 (referencia-elv)

Szövegek C++ -ban, a string osztály

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

Objektumorientált programozás C# nyelven

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

Programozás C++ -ban

Programozás alapjai II. (5. ea) C++ Objektummodell, öröklés, virtuális tagfüggvény

Már megismert fogalmak áttekintése

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

Bevezetés a programozásba II. 5. Előadás: Másoló konstruktor, túlterhelés, operátorok

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

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

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

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

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

1. Alapok. Programozás II

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

Programozás II. 6.Öröklés Dr. Iványi Péter

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

Programozás alapjai II. (5. ea) C++ Objektummodell, öröklés, virtuális tagfüggvény

Programozás módszertan

Pénzügyi algoritmusok

AA MEGOLDÓ ALADÁR AA

BME MOGI Gépészeti informatika 8.

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

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

Programozás C és C++ -ban

Programozási nyelvek Java

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

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

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

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

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

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?

C++ programozási nyelv

1.AA MEGOLDÓ BERCI AA 1.

Java és web programozás

A C++ öröklés. (Előfeltétel: 12. tétel ismerete)

Interfészek. PPT 2007/2008 tavasz.

Java és web programozás

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

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

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

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ó

Programozási alapismeretek 4.

Programozás alapjai C nyelv 8. gyakorlat. Mutatók és címek (ism.) Indirekció (ism)

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

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

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

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

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

és az instanceof operátor

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

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

Átírás:

Öröklés ism. Programozás alapjai II. (8. ea) C++ többszörös öröklés, cast, perzisztencia Szeberényi Imre BME IIT <szebi@iit.bme.hu> Egy osztályból olyan újabb osztályokat származtatunk, amelyek rendelkeznek az eredeti osztályban már definiált tulajdonságokkal, viselkedéssel. Analitikus - Korlátozó Egyszeres - Többszörös M Ű E G Y E T E M 1 7 8 2 C++ programozási nyelv BME-IIT Sz.I. 2017.03.28. - 1 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 2 - Többszörös öröklés Ha két osztály merőben különbözik, de mindkettőben valamit meg kell valósítani a másik számára. Az új osztálynak többféle arcot kell mutatnia (mutatókonverzió). Sokszor kiváltható barát függvényekkel, de nem a legjobb megoldás. Objektum és a környezet (pl. grafikus) kapcsolata. Többszörös öröklés/2 Két vagy több bázisosztályból származtatunk. Több OO nyelv nem támogatja, mert bonyolult implementálni. Ezekben a nyelvekben interfésszel váltják ki a többszörös öröklést. Leggyakrabban grafikus interfész és a modell kapcsolatánál használjuk. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 3 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 4 - Példa: Nyomógomb és callback fv. A grafikus rendszer kezeli a felhasználói eseményeket. Ha megnyomják (áthaladnak fölötte, elengedik, stb.), meghívja az alkalmazás megfelelő függvényét (callback), amit korábban az alkalmazás közölt a gombbal. Példa: Kapcsoló Gombnyomásra ki-be lehessen kapcsolni A (grafikus) felhasználói felületen megvalósított gomb megkap minden felhasználói inputot. Amikor azt kapja, hogy "megnyomták", akkor szól a kapcsolónak. Hogyan szól neki, ha nem ismeri? Próbálkozzunk származtatással! C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 5 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 6 -

Kapcsoló a grafikus felületből? Kapcsoló többszörös örökléssel Gomb callback() Kapcsoló Virtuális fv. callback() Megvalósítás A grafikának semmi köze a funkcionalitáshoz! Eddig úgy tudtuk, hogy a Kapcsoló a Drót-ból származik! A grafikus felülettől függ a működés? Drót set Funkciójában ebből származik Kapcsoló callback() GombCallback callback() Megvalósítás Gomb cb.obj.ref. Virtuális fv. Könnyű ilyenné konvertálni C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 7 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 8 - Kapcsoló megvalósítása class GombCallback { // callback funkcióhoz virtual void callback() = 0; // virtuális cb. függvény class Gomb { // felhasználói felület objektuma GombCallback &cb; // objektum referencia Gomb (GombCallback &t) :cb(t) {// referencia inic. void Nyom() { cb.callback(); // megnyomták... C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 9 - Kapcsoló megvalósítása/2 class Kapcsolo :public Drot, public GombCallback { int be; // állapot Az osztály kompatibilis a GombCallback void ki(); osztállyal, amin keresztül a Gomb osztály void be(); eléri a callback függvényt.... void callback() { if (be) ki(); else be(); // callback Kapcsolo k1; Gomb g1(k1); class Gomb { GombCallback &cb; Gomb (GombCallback &t) :cb(t) { void Nyom() { cb.callback(); C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 10 - Töbsz. öröklés + fv. overload Többszörös öröklés problémái void f() { void f(int) { struct B { void f(double){ Melyik f? struct AB : public A, public B { using A::f; using B::f; void f() { f(1); f(1.2);... AB ab; ab.f(); ab.f(5); ab.f(6.3); Többszörös öröklés különös figyelmet igényel, ha előfordulhat, hogy egy alaposztály különböző leszármazottjai "összetalálkoznak". Ekkor ún. rombusz v. "diamond" struktúra alakul ki. Példa: irodai hierarchia Feltételezés: A többszörös öröklésnél merőben eltérőek az alaposztályok, az azonos ű függvények más-más funkciót látnak el. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 11 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 12 -

Csop.vez. Irodai hierarchia Alkalmazott név, fizetés Hat.idejű.cs.v. Hat.idejű idő C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 13 - Irodai hierarchia /2 class Alkalmazott { protected: char [20]; // név double ; // fizetés Alkalmazott(char *n, double fiz); class CsopVez :public Alkalmazott { csop_t ; // azon. CsopVez(char *n, double f, csop_t cs) :Alkalmazott(n, f), (cs) { C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 14 - Irodai hierarchia /3 class HatIdeju :public Alkalmazott { time_t ido; // szerződése lejár ekkor HatIdeju(char *n, double f, time_t t) :Alkalmazott(n, f), ido(t) { class HatIdCsV :public CsopVez, public HatIdeju { HatIdCsV(char* n, double f, csop_t cs, time_t t) :CsopVez(n, f, cs), HatIdeju(n, f, t) { Két e és két fizetése van? C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 15 - Elérhetők ezek a mezők? class HatIdCsV :public CsopVez, public HatIdeju { HatIdCsV(char* n, double f, csop_t cs, time_t) :CsopVez(n, f, cs), HatIdeju(n, f, t) { void Kiir() { cout << CsopVez :: << endl; cout << HatIdeju :: << endl; A scope operátorral kiválasztható, tehát önmagában ez még nem lenne baj, de baj lehet belőle. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 16 - Memóriakép Miből fakad a probéma? struct CsopVez struct Alkalmazott struct HatIdCsV ido struct HatIdeju ido Többszörös elérés az öröklési gráfon. Miért nem vonja össze a fordító? A ek ütközése az öröklés megismert szabályai alapján még nem jelent bajt. Lehet hogy szándékos az ütközés. Automatikus összevonás esetén a kompatibilitás veszélybe kerülhet. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 17 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 18 -

Megoldás: Virtuális alaposztály class CsopVez :virtual public Alkalmazott {... Csak az öröklési lánc legvégén hívódik meg az alaposztály konstruktora. CsopVez(char *n, double f, csop_t cs) :Alkalmazott(n, f),// csak lánc végén (cs) { class HatIdeju :virtual public Alkalmazott{... class HatIdCsV :public CsopVez, public HatIdeju { HatIdCsV(char* n, double f, csop_t cs, time_t t) :Alkalmazott (n, f), // csak ha a lánc vége CsopVez(NULL, 0, cs), // tudjuk, hogy nem HatIdeju(NULL, 0, t) { // hívódik, ezért lehet NULL C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 19 - Virtuális alaposztály 1. Alaposztály adattagjai nem épülnek be a származtatott osztály adattagjaiba. A virtuális függvényekhez hasonlóan indirekt elérésűek lesznek. 2. Az alaposztály konstruktorát nem az első származtatott osztály konstruktora fogja hívni, hanem az öröklési lánc legvégén szereplő osztály konstruktora. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 20 - Memóriakép virt. alaposztállyal struct CsopVez &Alkalmazott struct Alkalmazott virtual struct HatIdCsV &Alkalmazott idő &Alkalmazott struct HatIdeju idő &Alkalmazott C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 21 - Irodai példa virt. alaposztállyal class Alkalmazott {... class HatIdeju :virtual public Alkalmazott{... class CsopVez :virtual public Alkalmazott {... class HatIdCsV :public CsopVez, public HatIdeju {... class HatIdCsVH :public HatIdCsV {... Melyik konstruktor hívja az Alkalmazott konstruktorát? Alkalmazott melos("lusta Dick", 100); // Alkalmazott HatIdeju grabo("grabovszki", 300); // HatIdeju CsopVez fonok("mr. Gatto ", 5000); // CsopVez HatIdCsV gore("mr. Tejfel", 3000); // HatIdCsV HatIdCsVH ("Safranek", 500); // HatIdCsVH Aki a lánc végen van. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 22 - És, ha nem lenne virtuális? class Alkalmazott {... class HatIdeju :public Alkalmazott{... class CsopVez :public Alkalmazott {... class HatIdCsV :public CsopVez, public HatIdeju {... class HatIdCsVH :public HatIdCsV {... Melyik konstruktor hívja az Alkalmazott konstruktorát? Alkalmazott melos("lusta Dick", 100); // Alkalmazott HatIdeju grabo("grabovszki", 300); // HatIdeju CsopVez fonok("mr. Gatto ", 5000); // CsopVez HatIdCsV gore("mr. Tejfel", 3000); // CsopVez, HatIdeju HatIdCsVH ("Safranek", 500); // CsopVez, HatIdeju Aki az első a láncban. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 23 - Konstruktor feladatai Öröklési lánc végén hívja a virtuális alaposztályok konstruktorait. Hívja a közvetlen, nem virtuális alaposztályok konstruktorait. Létrehozza a saját részt: beállítja a virtuális alaposztály mutatóit beállítja a virtuális függvények mutatóit hívja a tartalmazott objektumok konstruktorait végrehajtja a programozott törzset C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 24 -

Lehet-e konstruktorban virt. fv? Lehet, de nem az történik, amit várunk. Az alaposztály konstruktora a származtatatott o. konstruktora előtt fut le, így a virtuális függvénypointerek beállítása nem történik meg. B konstr. még nem futott. struct B :public A { B() { void f() { cout << "B::f"; A() { f(); virtual void f() { cout << "A::f"; Kiírás: A::f C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 25 - Destruktor feladatai Megszünteti a saját részt: végrehajtja a programozott törzset tartalmazott objektumok destruktorainak hívása virtuális függvénymutatók visszaállítása virtuális alaposztály mutatóinak visszaállítása Hívja a közvetlen, nem virtuális alaposztályok destruktorait. Öröklési lánc végén hívja a virtuális alaposztályok destruktorait. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 26 - Lehet-e destruktorban virt. fv? Lehet, de nem az történik, amit várunk. Az alaposztály destruktora a származtatatott o. destruktora után fut le, így a virtuális függvénypointerek már visszaálltak. B destr. már lefutott. struct B :public A { ~B() { void f() { cout << "B::f"; ~A() { f(); virtual void f() { cout << "A::f"; Kiírás: A::f C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 27 - Lehet-e konst/destr virtuális? Konstruktor NEM lehet virtuális! Virtuális destruktor használata viszont nagyon fontos, ha fentről szüntetünk meg. virtual ~A() { A *pa = new B; delete pa; class B :public A { char *p; C c; B() { p=new char[10]; ~B() { delete[] p; Ha nem virtualis, akkor nem szabadul fel a c adattag, és a dinamikus terület sem! C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 28 - Elkerülhető a többsz. öröklés? Egyes OO nyelvekben nincs többszörös öröklés, de van helyette interfész, amivel pótolható a hiánya. C++ -ban ilyen nincs, ezért teljesen nem kerülhető el. Biztosan nem kerülhető el, ha mindkét osztály "arcát" mutatni kell (pl. ny.gomb) mindkét osztályt valamiért alaposztállyá kell konvertálni (upcast) Mutatókonverzió újra Származtatott osztály a kompatibilitás révén könnyen konvertálható alaposztályra. Ez hívjuk "upcast"-nak. Leggyakrabban pointereket konvertálunk (heterogén gyűjtemény). Néha referenciát. (copy konstruktor hívása) Többszörös öröklésnél a konverzió nagy figyelmet igényel. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 29 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 30 -

Mut. konv. többszörös öröklésnél Alap1 * pb1 alap1 MulDer md; Alap2 * pb2 alap2 memóriakép kompatibilis új rész class Alap1 {... class Alap2 {... class MulDer: public Alap1, public Alap2 {... MulDer md; Alap1 * pb1 = &md; Alap2 * pb2 = &md; // mutató értékmódosítás! C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 31 - Konv. többsz. öröklésnél szárm.-ra MulDer * pmd alap1 alap2 új rész Alap2 b2; MulDer *pmd = (MulDer *) &b2; // mutató értékmódosítás! // nem létező adatmezőket és üzeneteket el lehet érni // veszély: explicit konverzió C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 32 - b2 Megbocsátható down cast Néha előfordul, hogy tudjuk, hogy egy adott mutató egy származtatott osztályból származik, de valamiért alappá konvertáltuk (pl. heterogén kollekció) Ekkor biztonságos a dynamic_cast használata, ami futási időben értékelődik ki. Ha MulDer* tipusú, akkor OK, egyébként NULL MulDer md; Alap *p = &md; MulDer *pa = dynamic_cast<mulder*>(p); C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 33 - cast átértékelése C: (típus) Explicit típuskonverziót végez. Használata körültekintést igényel. C programokban leginkább a malloc környékén fordul elő joggal. Eredménye nem lvalue. C++: Sokkal többször és sokkal több okból fordulhat elő joggal. A veszélyek csökkentésére több változata létezik: (dynamic_cast, static_cast, const_cast, reinterpret_cast, (tipus), tipus()) C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 34 - dynamic_cast szintaxis: dynamic_cast<t>(v) v alaposztályra hivatkozik, vagy pointer T származtatott osztályra hivatkozik, vagy void pointer virtual ~A(){ struct B :A { struct C :A { NULL polimorf A* apb = new B; A* apc = new C; B* bp1 = dynamic_cast<b*>(apb); B* bp2 = dynamic_cast<b*>(apc); C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 35 - static_cast szintaxis: static_cast<t>(v) v alaposztályra hivatkozik, vagy pointer T származtatott osztályra hivatkozik, vagy void pointer struct B :A { struct C :A { A* apb = new B; A* apc = new C; B* bp1 = static_cast<b*>(apa); B* bp2 = static_cast<b*>(apc); Fordítási időben történik, nincs futás idejű ellenőrzés! Jelzi, ami fordítási időben tilos. (pl. int* -> B*) C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 36 -

const_cast szintaxis: const_cast<t>(v) Csak a const vagy a volatile minősítő eltávolítására vagy előírására használható. const int a = 10; const int* b = &a; int* c = const_cast<int*>(b); *c = 30; //nincs ford.hiba.!!nem definit!! int a1 = 40; const int* b1 = &a1; int* c1 = const_cast<int*>(b1); *c1 = 50; // minden OK, mert a1 nem konst. reinterpret_cast szintaxis: reinterpret_cast<t>(v) Ellenőrzés és változtatás nélkül átalakítja v-t a megadott típusúvá. Igen veszélyes, de legalább könnyen felismerhető a forrásban. A const ill. volatile minősítés nem módosítható vele. struct B { B* p = new B; long l = reinterpret_cast<long>(p); C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 37 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 38 - (típus), típus( ) A C stílusú cast mellett használható még az úgyezett funkció stílusú cast is. Lehetőleg az úgyezett esített (dynamic_cast, static_cast, const_cast, reinterpret_cast) változatokat kell használni. Használatukkal a konverziókból adódó problémák sokkar könnyebben felfedezhetők. int i, j; double d; d = (double)i/j; d = double(i)/j; // funkció stílusú cast Explicit konstruktor (ism.) Az egyparaméterű konstruktorok egyben automatikus konverziót is jelentenek: pl: String a = "hello"; String a = String("hello"); Ez kényelmes, de zavaró is lehet: tfh: van String(int) konstruktor, ami megadja a string hosszát, de nincs String(char) konstruktor; ekkor: String b = 'x'; String b =String(int('x')); nem biztos, hogy kívánatos. Az aut. konverzió az explicit kulcsszóval kapcsolható ki. (pl: explicit String(int i);) C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 39 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 40 - Explicit konstruktor példa: class Komplex { double re, im; Komplex(double re = 0, double im = 0) :re(re), im(im){ void valamifv(class Komplex); Obj Attr. Perzisztencia Obj Attr. int main() { Komplex k1 = 12; // OK.... valamifv(12); // Lehet, h. nem ezt akarta A perzisztens objektumok állapota elmenthető és visszatölthető egy későbbi időben, esetleg másik gépen létrehozott objektumba. A visszatöltött objektum "folytatja" a működést. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 41 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 42 -

Perzisztencia/2 Az objektum a saját állapotát képes kiírni egy adatfolyamba serializáció Az objektum a saját állapotát képes beolvasni egy adatfolyamból deserializáció Szempont lehet a hordozható külső formátum is. Ez különösen fontos elosztott rendszereknél. A perzisztenciát gyakran többszörös örökléssel vagy interfésszel oldják meg. Perzisztencia örökléssel I./1 class Serialize { int size; // kírandó adat mérete Serialize(int s) :size(s) { // méret beállítása void write(ostream& os) const { os.write((char *)this, size); // kiírás void read(istream& is) const { is.read((char *)this, size); // beolvasás C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 43 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 44 - Perzisztencia örökléssel I./2 class Complex { Képes kiírni ill. visszatölteni double re, im;... class PComplex : public Serialize, public Complex { PComplex(double re, double im) : Complex(re, im), Serialize(sizeof(PComplex)) { int main() { ofstream f1("f1.dat"); PComplex k1(1, 8); k1.write(f1); return 0; Származtatott mérete int main() { ifstream f1("f1.dat"); PComplex k1; k1.read(f1); return 0; C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 45 - A sorrendre érzékeny! class PComplex : public Serialize, public Complex {... Complex Serializable re size im write((char*)this,size) PComplex:: this Serialize:: this Complex:: this PComplex size re im class PComplex : public Complex, public Serialize {... C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 46 - re im size Problémák Pointerek visszatöltésének nincs értelme. Veszélyes a kód: A öröklés sorrendjére érzékeny. A Serialize osztálynak kell elsőnek szerepelni. Mi van a virtuális függvények mutatóival? Külső reprezentáció nem hordozható. Ötletnek nem rossz, de a gyakorlatban használhatatlan! Van megoldás? C++-ban nehéz automatizálni a serializációt. Néhány könyvtár ad támogatást (pl. boost, MFC, s11n) Fapados, de működő megoldás: magára az objektumra kell bízni az adatfolyammá történő alakítást ill. visszaalakítást. Kellő körültekintéssel el kell készíteni a megfelelő virtuális függvényeket. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 47 - C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 48 -

Használható megoldás class Serializable { virtual void write(ostream& os) const = 0; // kiíró virtual void read(istream& is) = 0; // beolvasó virtual ~Serializable() { // ne legyen probléma az upcast class String { protected: // hogy hozzáférjen a származtatott char *p; // van dinamikus adattag int len; String(char *s = "" ) { len = strlen(s); p = new char[len+1]; strcpy(p, s);... C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 49 - Használható megoldás class PString : public Serializable, public String { PString(char *p = "") : String(p) { void write(ostream& os) const { os << len << ' '; // separator os.write(p, len); // a string kiírása void read(istream& is) { delete[] p; (is >> len).ignore(1); // len beolv., eldobjuk a szepart. p = new char [len+1];// új terület kell is.read(p, len); // len db karaktert olvasunk p[len] = 0; // lezáró nulla C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 50 - Kérdések, megjegyzések Fontos, hogy a read() metódus pontos tükörképe legyen a write()-nak. Fontos a megfelelő reprezentáció kiválasztása. Kézenfekvő mindent szöveggé alakítani. Ekkor numerikus kiírások után kell szeparátor, amit a beolvasáskor el kell dobni. Pointerek és referenciák kezelése külön figyelmet igényel. Miért kell többszörös öröklés? ha módosítható az osztály megoldható töbsz. nélkül ha nincs kezünkben az osztály csak ez a lehetőség C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 51 -