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
[email protected]
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
Objektumok
Objektumok Objektumok létrejöhetnek: Automatikusan Globális változóként Osztály tagjaiknént ...
Konstruktor: Objektumok létrejöttekor fut le Feledata: Osztály kezdeti inicializálása (Memória foglalás, változók beállítása)
Destruktor: Objektumok 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
Objektumok
Példa: 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
Osztályok, objektumok
Objektumok
Példa: Destruktor
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
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
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) Objektumok 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
Objektumok
Dinamikus memóriakezelés a C++-ban Példa: 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 Fodor A. (Pannon Egyetem)
Programozás
delete[] kell!!! 2010. március 11.
8 / 31
Osztályok, objektumok
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 Példa: void fv(char ch) { CPelda a; CPelda b; if (ch == ’c’) { CPelda c; // ... } CPelda d; // ... }
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
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!!! Példa: CPelda a; CPelda b=a;
Érdemes másoló konstruktort készíteni ilyenkor, és az értékadás operátorát felülírni Példa: class CPelda { // ... CPelda(const CPelda&); CPelda& operator=(const CPelda&); };
Fodor A. (Pannon Egyetem)
Programozás
// másoló konstruktor // másoló értékadás
2010. március 11.
10 / 31
Osztályok, objektumok
Objektumok
Objektum létrehozása és megsemmisítése Lokális változó - Példa class CPelda { // ... CPelda(const CPelda&); CPelda& operator=(const CPelda&); }; CPelda::CPelda(const CPelda& cp) { p = new string[cp.darab]; // for(int i=0;... }
// másoló konstruktor // másoló értékadás
// másoló konstruktor
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
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 Példa: 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
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) Példa: 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
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ó Példa: 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
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) Példa: CPelda* CPelda* CPelda* CPelda*
p1 p2 p3 p4
= = = =
delete p1; delete[ ] p2; delete[ ] p3; delete p4;
new new new new
CPelda; CPelda[100]; CPelda; CPelda[100];
// 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
* p1 = new vector(100); CPelda* p2 = new CPelda; delete p1; delete p2; Fodor A. (Pannon Egyetem)
Programozás
2010. március 11.
15 / 31
Osztályok, objektumok
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 Példa: 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
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 Példa: 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
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
Példa: 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
Objektumok
Objektum létrehozása és megsemmisítése
Objektumok 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) Példa: void* operator new(size_t, void* p) { return p; }
Fodor A. (Pannon Egyetem)
Programozás
// explicit elhelyező oper
2010. március 11.
19 / 31
Osztályok, objektumok
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
Származtatott osztályok
Osztály, osztályhierarchia
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
Származtatott osztályok - Példa 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
Származtatott osztályok
Osztályok viszonyának ábrázolása
Fodor A. (Pannon Egyetem)
Programozás
2010. március 11.
24 / 31
Származtatott osztályok
Származtatott osztályok
Öröklődés tulajdonságai
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
Származtatott osztályok
Származtatott osztályok
Tagfüggvények 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(); };
Fodor A.
class Kurzus:public Tantargy { int NumHallgato; string Terem; public: string GetTerem(); }; Egyetem) (Pannon Programozás
2010. március 11.
26 / 31
Származtatott osztályok
Származtatott osztályok
Tagfüggvények 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
Származtatott osztályok
Származtatott osztályok
Virtuális függvények
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ó Példa: 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
Származtatott osztályok
Konstruktorok és destruktorok 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 Példa: class Tantargy { string Nev; string Oktato; char Ora_E; char Ora_L; char Ora_Gy; public: Tantargy(const string& pNev, const string& pOktato); };
Fodor A.
class Kurzus:public Tantargy { int NumHallgato; string Terem; public: Kurzus(const string& pNev, const string& pOktato, const string& pT (Pannon Programozás 2010. március 11. 29 / 31 }; Egyetem)
Származtatott osztályok
Származtatott osztályok
Konstruktorok és destruktorok Példa: 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
Származtatott osztályok
Konstruktorok és destruktorok
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 ! Példa:
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