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

Osztályok. 4. gyakorlat

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

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

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

C++ programozási nyelv Konstruktorok-destruktorok

500. AA Megoldó Alfréd AA 500.

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

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

Objektumorientált programozás C# nyelven

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

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++

OOP #14 (referencia-elv)

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++

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

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

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

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

Objektumorientált programozás C# nyelven

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

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

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

Programozási nyelvek Java

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

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

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

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á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

és az instanceof operátor

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

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

Interfészek. PPT 2007/2008 tavasz.

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

Java és web programozás

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

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

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ó

Java II. I A Java programozási nyelv alapelemei

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

Átírás:

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> M Ű E G Y E T E M 1 7 8 2 C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 1 -

Öröklés ism. 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 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. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 3 -

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. - 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. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 5 -

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. - 6 -

Kapcsoló a grafikus felületből? Gomb callback() Kapcsoló Virtuális fv. callback() 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? Megvalósítás C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 7 -

Kapcsoló többszörös örökléssel Drót set GombCallback callback() Gomb cb.obj.ref. Funkciójában ebből származik Kapcsoló callback() Megvalósítás Virtuális fv. Könnyű ilyenné konvertálni C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 8 -

Kapcsoló megvalósítása class GombCallback { // callback funkcióhoz public: virtual void callback() = 0; // virtuális cb. függvény class Gomb { // felhasználói felület objektuma GombCallback &cb; // objektum referencia public: 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 public: void ki(); void be();... void callback() { if (be) ki(); else be(); } // callback Kapcsolo k1; Gomb g1(k1); Az osztály kompatibilis a GombCallback osztállyal, amin keresztül a Gomb osztály eléri a callback függvényt. class Gomb { GombCallback &cb; public: 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 struct A { 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); Feltételezés: A többszörös öröklésnél merőben eltérőek az alaposztályok, az azonos nevű függvények más-más funkciót látnak el. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 11 -

Többszörös öröklés problémái 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 C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 12 -

Irodai hierarchia Alkalmazott név, fizetés Csop.vez. csoport Hat.idejű idő Hat.idejű.cs.v. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 13 -

Irodai hierarchia /2 class Alkalmazott { protected: char nev[20]; // név double fizetes; // fizetés public: Alkalmazott(char *n, double fiz); class CsopVez :public Alkalmazott { csop_t csoport; // csoport azon. public: CsopVez(char *n, double f, csop_t cs) :Alkalmazott(n, f), csoport(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 public: HatIdeju(char *n, double f, time_t t) :Alkalmazott(n, f), ido(t) { } class HatIdCsV :public CsopVez, public HatIdeju { public: HatIdCsV(char* n, double f, csop_t cs, time_t t) :CsopVez(n, f, cs), HatIdeju(n, f, t) { } Két neve é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 { public: HatIdCsV(char* n, double f, csop_t cs, time_t) :CsopVez(n, f, cs), HatIdeju(n, f, t) { } void Kiir() { cout << CsopVez :: nev << endl; cout << HatIdeju :: nev << 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 -

struct CsopVez nev fizetes csoport Memóriakép struct Alkalmazott nev fizetes struct HatIdCsV nev fizetes csoport nev fizetes ido struct HatIdeju nev fizetes ido C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 17 -

Miből fakad a probéma? Többszörös elérés az öröklési gráfon. Miért nem vonja össze a fordító? A nevek ü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. - 18 -

Megoldás: Virtuális alaposztály class CsopVez :virtual public Alkalmazott {... public: 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 csoport(cs) { } class HatIdeju :virtual public Alkalmazott{... class HatIdCsV :public CsopVez, public HatIdeju { public: 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 csoport &Alkalmazott nev fizetes nev fizetes struct Alkalmazott nev fizetes virtual struct HatIdCsV csoport &Alkalmazott idő &Alkalmazott struct HatIdeju idő &Alkalmazott nev fizetes 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"; } struct A { 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"; } struct A { ~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. struct A { virtual ~A() { A *pa = new B; delete pa; class B :public A { char *p; C c; public: 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) C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 29 -

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. - 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 b2 ú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 -

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 struct A { virtual ~A(){} struct B :A { struct C :A { polimorf A* apb = new B; A* apc = new C; NULL 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 A { 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. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 37 -

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. - 38 -

(típus), típus( ) A C stílusú cast mellett használható még az úgynevezett funkció stílusú cast is. Lehetőleg az úgynevezett nevesí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 C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 39 -

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. - 40 -

Explicit konstruktor példa: class Komplex { double re, im; public: Komplex(double re = 0, double im = 0) :re(re), im(im){ } void valamifv(class Komplex); int main() { Komplex k1 = 12; // OK.... valamifv(12); // Lehet, h. nem ezt akarta C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 41 -

Perzisztencia Obj Attr. Obj Attr. 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. - 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. C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 43 -

Perzisztencia örökléssel I./1 class Serialize { int size; // kírandó adat mérete public: 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. - 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 { public: 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 re im size class PComplex : public Complex, public Serialize {... } C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 46 -

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! C++ programozási nyelv BME-IIT Sz.I. 2016.04.12. - 47 -

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. - 48 -

Használható megoldás class Serializable { public: 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; public: 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 { public: 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 -