Programozás Osztályok, Származtatott osztályok Fodor Attila Pannon Egyetem Műszaki Informatikai Kar Villamosmérnöki és Információs Rendszerek Tanszék foa@almos.vein.hu 2010. március 11.
Beadandó feladat Beadandó feladat Beadandó feladat - ZH-k kiváltására Készítsen olyan osztályokat, amely akalmas a következő ideális alkatrészek viselkedését modellezni: Feszültség forrás, áramforrás Rövidzár, szakadás Ellenállás, kondenzátor, tekercs Az osztályok támogassák különböző alkatrészek soros és párhuzamos kapcsolását Egy példán mutassa be a feszültség- és áramosztót Az osztályok segítségével készítsen néhány egyszerű példát, melyben szemléltetve van a soros és párhuzamos kapcsolás. Készítse el az osztályok dokumentációját Az első 5 helyes megoldást beadó hallgató kap felmentést a ZH-k megírása alol. Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 2 / 31
Osztályok, objektumok létrejöhetnek: Automatikusan Globális változóként Osztály tagjaiknént... Konstruktor: létrejöttekor fut le Feledata: Osztály kezdeti inicializálása (Memória foglalás, változók beállítása) Destruktor: eltávolításakor/törlésekor fut le Feledata: Osztály által használt erőforrások felszabadítása (Memória felszabadítás) Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 3 / 31
Osztályok, objektumok Alapértelmezett konstruktor Példa (Konstruktor implementációja): class CPelda public: CPelda(int pyear=0, int pmonth=0, int pday=0, int phour=100, int pmin=100, int psec=100); }; CJDate::CPelda(int pyear, int pmonth, int pday, int phour, int pmin, int psec) // Osztályváltozók beállítása // Memória foglalás is lehetne it... } Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 4 / 31
Destruktor Osztályok, objektumok Példa (Destruktor implementációja): class CPelda public: ~CPelda(); }; CPelda::~CPelda() // Memória felszabadítás } A használat végén biztosan fel van szabadítva a memória Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 5 / 31
Osztályok, objektumok Dinamikus memóriakezelés a C++-ban Változók élettartamának szabályozása Futási időben történő memóra foglalás és felszabadítás new operátor A szabad tárban (free store, heap, dinamikus memória) objektum létrehozására szolgál A dinamikus memóriakezelés rendszer szinten van megoldva (A malloc C++-os megfelelője, csak sokkal kényelmesebb a használata) new[] operátor A szabad tárban (free store, heap, dinamikus memória) tömb létrehozására szolgál Nem tölti fel kezdőértékkel a memóriát new és a new[] operátorok is felülírhatóak Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 6 / 31
Osztályok, objektumok Dinamikus memóriakezelés a C++-ban delete operátor new operátorral lefoglalt memória felszabadítása (csak a new segítségével lefoglaltra) item Minden objektumot csak egyszer lehet felszabadtani Ha egy objektum a delete operatorral törölve lett, akkor ahhoz nem lehet már hozzáférni (hozzáférési kísérlet is hibának számít) delete[] operátor A szabad tárban (free store, heap, dinamikus memória) tömb felszabadítására szolgál "Szemétgyűjtő" (garbage collector) törlését segíti, melyekre nincsen hivatkozás C++ nem támogatja delete és a delete[] operátorok is felülírhatóak Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 7 / 31
Osztályok, objektumok Dinamikus memóriakezelés a C++-ban CJDate *p, *p2; p = new CJDate(); p2 = new CJDate(2010, 3, 11, 14, 0, 0); CJDate &r = *p; int y = r.getyear(); int m = r.getmonth(); // Referencia létrehozása delete p; delete p2; delete p2; // HIBA!!! Példa (tömb lefoglalása): char *pc3 = new char[100]; delete pc3; // CJDate *p3 = new CJDate[100](); CJDate *p3 = new CJDate[100]; delete[] p3; delete p3; // Problémás lehet delete[] kell!!! Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 8 / 31
Példa futása: Konstruktorok: a b (c) d Destruktorok: d (c) b a Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 9 / 31 Osztályok, objektumok Objektum létrehozása és megsemmisítése Lokális változó Konstruktora mindig végrehajtódik, ha új példány keletkezik, mert a blokk végrehajtása elindul Destruktor végrehajtására akkor történik, amikor kilépünk a változó blokkjából void fv(char ch) CPelda a; CPelda b; if (ch == c ) CPelda c; } CPelda d; }
Osztályok, objektumok Objektum létrehozása és megsemmisítése Lokális változó Ha másolással inicializáljuk a változót nem fut le a konstruktor!!! CPelda a; CPelda b=a; Érdemes másoló konstruktort készíteni ilyenkor, és az értékadás operátorát felülírni class CPelda CPelda(const CPelda&); // másoló konstruktor CPelda& operator=(const CPelda&); // másoló értékadás }; Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 10 / 31
Osztályok, objektumok Objektum létrehozása és megsemmisítése Lokális változó - Példa class CPelda }; CPelda(const CPelda&); CPelda& operator=(const CPelda&); // másoló konstruktor // másoló értékadás CPelda::CPelda(const CPelda& cp) // másoló konstruktor p = new string[cp.darab]; // for(int i=0;... másolás } CPelda& CPelda::operator=(const CPelda& t) // értékadás if (this!= &t) // ön-értékadás (t = t) elekrüéáse delete[] p; p = new string[cp.darab]; // for(int i=0;... másolás } return *this; } Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 11 / 31
Osztályok, objektumok Objektum létrehozása és megsemmisítése Szabad memóriából történő lefoglalással Dinamikus memoriafoglalás esetén (new operator) A konstruktort az operator hívja meg Memória felszabadítása delete operator segítségével delete operator hívja meg a destruktort CPelda *p, *p2; p = new CPelda(); p2 = new CPelda(1, 2, 3); delete p; delete p2; Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 12 / 31
Osztályok, objektumok Objektum létrehozása és megsemmisítése Osztály típusú tagok Egy osztály változójának típusa egy másik osztály Tag-kezdőérték lista (member initializer) class CObserve string Name; string Star; CJDate ODate; double Magnitude; CObserve(const string& pstar, CJDate pdate, const double& pmagn); }; CObserve::CObserve(const string& pstar, CJDate pdate, const doubl : Name(), Star(pStar), ODate(pDate), Magnitude(pMagn) } Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 13 / 31
Osztályok, objektumok Objektum létrehozása és megsemmisítése Tömbök Ha egy osztálynak van alapértelmezett konstruktora, akkor ilyen osztályú objektumok tömbje is meghatározható class CPelda CPelda(); // alapértelmezett konstruktor }; CPelda peldany[15]; Mind a 15 példány az alapéertelmezett konstruktorral fog meghívódni Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 14 / 31
Osztályok, objektumok Objektum létrehozása és megsemmisítése Tömbök Dinamikusan kezelt tömböknél figyelni kell a felszabadításra delete vagy delete[] nem felcserélhető szabvány szerint!!! (Bizonyos fordítók/változatok nyilvántartják, hogy tömb volt e lefoglalva) CPelda* p1 = new CPelda; CPelda* p2 = new CPelda[100]; CPelda* p3 = new CPelda; CPelda* p4 = new CPelda[100]; delete p1; delete[ ] p2; delete[ ] p3; delete p4; // hiba, kerülendő // hiba, kerülendő Kiküszöbölés: (dinamikusan még bővíthető is) vector template osztály alkalmazása vector<cpelda>* p1 = new vector<cpelda>(100); CPelda* p2 = new CPelda; delete p1; delete p2; Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 15 / 31
Osztályok, objektumok Objektum létrehozása és megsemmisítése Lokális statikus adatok Konstruktora akkor hajtódik végre, amikor a futás először eljut a példányig void fv(char ch) static CPelda tbl; if (ch == b ) static CPelda tbl2; } } fv( a ); fv( b ); fv( c ); Destruktor végrehajtására akkor történik, amikor kilépünk a programból Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 16 / 31
Osztályok, objektumok Objektum létrehozása és megsemmisítése Globális adatok A main() függvény lefutása előtt jönnek létre Konstruktor a main() függvény előtt hajtódik végre Dinamikus könyvtárak esetében a dinamikus kód programhoz való kapcsolódásakor fut le Több változó esetén a definició sorrendjébe történik a konstruktorok végrehajtása CComplex c; CPelda pelda; void main(void) } Destruktor végrehajtására akkor történik, amikor kilépünk a main() függvényből Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 17 / 31
Osztályok, objektumok Objektum létrehozása és megsemmisítése Ideiglenes objektumok Legtöbbször aritmetikai kifejezéseknél jön létre Nem törlödik, ha nevesített változónak ad kezdőértéket vagy referenciához van kötve CComplex c(1,1), c2(2,2), c3(3,3); c = (c+c2)*c3; double re = (c+c2).getre(); double im = (c+c2).getim(); Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 18 / 31
Osztályok, objektumok Objektum létrehozása és megsemmisítése meghatározott helyre történő elhelyezése new operátor heap-ben foglalja le a memóriát és oda hozza létre az objektumot Ha meg akarjuk adni, hogy hova kerüljön az új objektum, akkor meg kell változtatni a new operátort Kell egy újabb paraméter (memóriacím) void* operator new(size_t, void* p) return p; } // explicit elhelyező oper Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 19 / 31
Osztályok, objektumok Objektum létrehozása és megsemmisítése Union (Unió) Az union olyan adatszerkezet (struct), amelyben minden tag címe azonos Egy uniónak lehetnek tagfüggvényei Az uniónak nem lehetnek statikus tagjai Nem lehet olyan adattagja az uniónak, melynek konstruktora van Nem tudja a fordító, hogy milyen típusú adat van benne Felhasználás: Leginkább alacsony szinten Olyan osztály belsejében ahol nyilvántartják, hogy mi van az unióban Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 20 / 31
Származtatott osztályok Osztály, osztályhierarchia Származtatott osztályok Osztály, osztályhierarchia C++ a Simula nyelvből vette mindkettő fogalmat A tervezési elv is a Simula nyelvből lett átvéve: Programban használt fogalmak modellezésére osztályok alkalmazása Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 21 / 31
Származtatott osztályok Származtatott osztályok - Példa Származtatott osztályok Vegyünk két adatszerkezet tantárgyak, kurzusok eltárolására struct Tantargy string Nev; string Oktato; char Ora_E; char Ora_L; char Ora_Gy; }; struct Kurzus string Nev; string Oktato; char Ora_E; char Ora_L; char Ora_Gy; int NumHallgato; string Terem; }; Látható, hogy vannak azonos tulajdonságaink (adattagjaink) Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 22 / 31
Származtatott osztályok Származtatott osztályok Származtatott osztályok (Derived), öröklés A Kurzus-t le tudjuk származtatni a Tantargy osztályból struct Kurzus:public Tantargy int NumHallgato; string Terem; }; A két osztály közötti kapcsolat neve: öröklődés (öröklés, inheritance) A Kurzus a Tantargy-ból származik A Tantargy a Kurzus bázisosztály/őse Az öröklődés miatt adottak lesznek a Tantargy tulajdonságai Név, oktató, óraszámok Új tulajdonságok: Hallgatók száma, terem Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 23 / 31
Származtatott osztályok Osztályok viszonyának ábrázolása Származtatott osztályok Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 24 / 31
Származtatott osztályok Öröklődés tulajdonságai Származtatott osztályok A Kurzus a Tantargy-ból származik Kurzus osztály egyben Tantargy osztály is Rendelkezik minden tulajdonságával A Kurzus osztályt használhatjuk Tantargy osztály helyett is A Tantargy osztályt NEM használhatjuk Kurzus osztály helyett is Nem rendelkezik minden tulajdonságával (például: terem) Egy származtatott osztálynak egy bázis osztály nyilvános bázisosztálya, akkor a Base* típusú változó típuskényszerítés nélkül kaphat Derived* típusú értéket Mutatók és referenciák: Származtatott osztály objektumait úgy kezelhetjük, mint a bázisosztály objektumait Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 25 / 31
Tagfüggvények Származtatott osztályok Származtatott osztályok Probléma: Bárhonnan modosíthatóak az adattagok struct alkalmazásakor nem lehet az elérési tulajdonságokat szabályozni Megoldás: Osztály alkalmazása class Tantargy string Nev; string Oktato; char Ora_E; char Ora_L; char Ora_Gy; public: string GetName(); }; class Kurzus:public Tantargy int NumHallgato; string Terem; public: string GetTerem(); }; Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 26 / 31
Származtatott osztályok tagfüggvényei elérhetik a bázisosztály nyilvános (public) és védett (protected) változóit, függvényeit Származtatott osztály NEM éri el a bázisosztály privát (private) tagjait Ha el lehetne érni: Ki lehetne kerülni az elérés szabályozását Ha hozzáférne, akkor a private elérés értelmetlenné válna A védett (protected) tag a származtatott osztályok számára úgy viselkedik, mint egy nyilvános (public), a többiek számára azonban privátnak minősül Ahol megengedhető ott védett (protected) és ne privát (private) tagokat érdemes használni Érdemes úgy kialakítani az osztályokat, hogy a származtatott osztály a bázisosztálynak csak a nyilvános (public) tagjait használja Az ősosztály tagfüggvényei felülírhatóak Hivatkozás az ősosztály függvényére a :: (hatókör) operátorral lehetséges Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 27 / 31 Tagfüggvények Származtatott osztályok Származtatott osztályok
Virtuális függvények Származtatott osztályok Származtatott osztályok A virtual szó a Simulában és a C++-ban azt jelenti, hogy az adott osztályból származtatott osztályban később felülírható class CJDate virtual int GetYear(); virtual int GetMonth(); virtual int GetDay(); }; A fordító a virtuális függvényekra mutató mutatókat egy táblázatban tárolja Virtuális Függvénytábla (VTBL) Minen virtuális függvényt tartalmazó osztálynak van egy VTBL táblája Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 28 / 31
Származtatott osztályok Konstruktorok és destruktorok Származtatott osztályok Származtatott osztályoknak lehet konstruktora és destruktora Ha a bázisosztálynak van, akkor azokat meg kell hívni Ha nincsen alapértelmezett értéke az ősosztály konstruktorának, akkor azt nekünk kell a megfelelő paraméterekkel meghívni class Tantargy string Nev; string Oktato; char Ora_E; char Ora_L; char Ora_Gy; public: Tantargy(const string& pnev, const string& poktato); }; class Kurzus:public Tantargy int NumHallgato; string Terem; public: Kurzus(const string& pnev, const string& poktato, const string& pt Fodor A. (Pannon }; Egyetem) Programozás 2010. március 11. 29 / 31
Származtatott osztályok Konstruktorok és destruktorok Származtatott osztályok Tantargy::Tantargy(const string& pnev, const string& poktato) :Nev(pNev), Oktato(pOktato) } Kurzus::Kurzus(const string& pnev, const string& poktato, const string :Tantargy(pNev, poktato), Terem = pterem } Az ősosztály konstruktora a megadott paraméterekből kap értéket. Úgy hívjuk meg, mintha az tagja lenne az osztálynak Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 30 / 31
Származtatott osztályok Konstruktorok és destruktorok Származtatott osztályok A származtatott osztály konstruktora csak a saját adattagjai és a bázisosztály konstruktorának adhat meg kezdőértéket! Bázisosztály tagjainak nem adhat értéket! Kurzus::Kurzus(const string& pnev, const string& poktato, const string :Nev(pNev), //Hiba Oktato(pOktato) //Hiba } Fodor A. (Pannon Egyetem) Programozás 2010. március 11. 31 / 31