Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban
Tartalom OOP ismétlés Osztályok létrehozása Adattagok láthatóságai, elnevezési ajánlások Konstruktor, destruktor this pointer Statikus és dinamikus objektum példányosítás
OOP Ismétlés
Objektumorientáltság Az objektum valamilyen valós életből vett egyed Lehet konkrét, fizikai: személy, kártya, autó Lehet konkrét, nem fizikai: kurzus, hozzászólás Minden objektumot három fontos jellemző ír le Állapot milyen? Viselkedés mit tud csinálni? Identitás ki is ő? A fenti példák mindegyike rendelkezik mindhárommal
Állapot Az objektumot jellemezhetjük a tulajdonságaival (attribútumok) Minden tulajdonság sokféle értéket vehet fel (pl. születési év bármilyen egész szám lehet) Az objektum állapota a tulajdonságnak egy bizonyos kombinációja Pl. egy hallgató állapota lehet 1998-ban született, aktív féléves, 3.5 az átlaga és ABCEABC.SZE az EHA kódja
Viselkedés Az a mód, ahogy viselkedhet, reagálhat külső kérésekre Megmondja, hogy mit csinálhat és azt hogyan teszi Ezeket az objektum metódusai (~függvény) írják le Pl. a hallgató vehet fel vizsgát, adhat le vizsgát, passziváltathatja magát Tehát akkor lesz egy vizsgatfelvesz(), egy vizsgatlead() és egy passzivaltat() metódusa
Identitás Minden egyes objektum egyedi Még akkor is, ha mindenük egyforma A valóságban is, attól, hogy valakik ugyan arra a kurzusra járnak, ugyan abban az évben születtek, még különböző emberek Ettől függetlenül mégis hasonlítanak egymásra Ugyan azokkal a tulajdonságokkal jellemezzük őket Ugyan azokat tudják csinálni
Osztály Az osztály lesz az, ami tárolja a hasonlóságot Itt írjuk le, hogy milyen (mik az attribútumai) Miket tud csinálni (milyen metódusai vannak) Hogy kapcsolódnak más objektumokhoz Az osztály olyasmi lesz az objektumnak, mint az adattípus a változónak, tehát ez lesz a típusa
Objektum Az osztály egy konkrét példánya az objektum Ennek a létrehozását példányosításnak hívjuk Egy osztályból több objektum is lehet Egy objektum csak egy osztály példánya lehet
OOP paradigma alappillérei Abstraction Ami az osztályra tartozik, az legyen is ott Ami csak rá tartozik, azt csak ő lássa Encapsulation + Data hiding Encapsulation Minden, ami összetartozik (adattag, metódus), zárjuk össze egy osztályba Inheritance A közös részeket át lehet örökíteni Újrafelhasználható(bb) kódot írhatunk Polymorphism Egy objektum helyzettől függően több alakot is felvehet Gyerek lehet ős, ős nem lehet gyerek
Öröklődés Az öröklés az OOP paradigma egyik pillére Ha egy osztályt örököltetünk egy másikból, akkor az új (gyerek) megkapja a régitől (ős) az összes tulajdonságát és viselkedését Ezeket módosíthatja (ha engedjük), illetve kiegészítheti újakkal Overriding: ha definiálunk egy metódust, amilyen már volt az ősben, akkor felülírom, futásidőben dől el, hogy melyiket hívjuk
Öröklődés Az öröklődés specializáció/általánosító kapcsolat, attól függ, honnan nézzük A gyermek specializálja (szűkíti) az őst Az ős osztály a gyereknek egy általános (bővebb) esete Többszörös öröklődés: Javaban nincs! - de C++-ban lesz Egyszerre több dolog öröklése máshogy van megoldva, ld. később
Láthatóság OOP paradigma egyik fontos eleme: egységbezárás (encapsulation) Zárjuk össze és rejtsük el a külvilág elől, amit csak lehet Ezt a láthatóság módosításával érhetjük el
Polimorfizmus Leszármazott típusú osztályt mindig használhatunk ős típus helyett Metódus paraméterként Tömbben Objektum referenciánál Visszatérési értékként Őst viszont nem tudunk leszármazottra alakítani Kivéve, ha eredetileg leszármazott típusú volt és upcast miatt lett ős Ld. később
Konstruktor Speciális metódus, ami az objektum példányosításakor hívódik meg Példányosítást már nem tudja megakadályozni Kezdeti teendők megvalósítására szolgál A neve ugyan az, mint az osztálynak Nincs visszatérési értéke Lehet többféle paraméterlistája is lehet - overloading Általában public Minden osztálynak van default konstruktora
Overloading Azonos metódusnév, különböző paraméterlista A híváskor kapott paraméterek alapján dönt
Osztályok C++-ban
Osztályok létrehozása C++-ban az osztályok felfoghatók egy speciális névtérnek is Ez viszont nem folytatható Létrehozni a class kulcsszóval lehet (mint Javaban) Az adattagokat, metódusokat { } zárójelpár között soroljuk fel A záró } után ; kell!
Adattagok láthatósága A Javaban megismert láthatóságok itt is léteznek private csak az adott osztályban látható protected leszármazottak is láthatják (ld. Később) public bárki láthatja Alapértelmezett láthatóság a private
Adattagok láthatósága Láthatóságot nem kell minden adattag/metódus elé kirakni Elég egyszer, majd : után felsorolni az ilyen láthatósággal rendelkező adattagokat, metódusokat
Adattagok láthatósága Protected adattag és metódus class Kor { protected: double sugar; double kerulet(); }
Adattagok láthatósága Protected adattag és public metódus class Kor { protected: double sugar; public: double kerulet(); }
Elnevezési konvenciók Magyar jelölés: az adattag nevéven legyen benne a típusa is pl. double dsugar; int ievszam; Az adattagok nevét kezdjük m_ prefixszel, így elkülönülnek a lokális változóktól A kettő használható együtt is, pl. double m_dsugar; int m_ievszam;
Konstruktor Konstruktort már ismerjük Javaból, röviden: Speciális metódus Neve megegyezik az osztály nevével Nincs visszatérési értéke Egy objektum példányosításakor hívódik meg Értékadásra, erőforrások lefoglalására használjuk Az objektum létrejöttét már nem tudja megállítani Lehet több konstruktor is, aminek a neve ugyan az, de más paramétereket vár Default konstruktor: minden osztálynak van, felüldefiniálható az is
Konstruktor class Kor { double m_dsugar; public: Kor(double); }; Kor::Kor(double r) { m_dsugar = r; }
Destruktor Ilyen nem volt Javaban (ott van Garbage Collector) Az objektum törlésekor hívódik meg (de a törlést már nem tudja megakadályozni) Erőforrás felszabadításra használjuk (memória, fájl, hálózati kapcsolat...) Neve ugyan az, mint az osztály neve, csak az elején egy ~ van Nincs visszatérési értéke, nincs paramétere, csak egy lehet belőle
Destruktor class Kor { double m_dsugar; public: Kor(double); ~Kor(); }; Kor::Kor(double r) { m_dsugar = r; } Kor::~Kor(){}
This pointer Javaban is volt this, itt is az a jelentése Az aktuális objektumra mutat A this egy pointer Pl. Adattagjára a -> operátorral hivatkozhatunk (mint C-ben a dinamikusan foglalt struktúra mezőjére) Kor::Kor(double r) { } this->m_dsugar = r;
Objektum példányosítás C++-ban két módon lehet objektumokat létrehozni 1. stacken: statikus példányosítás 2. heapen: dinamikus példányosítás
Statikus példányosítás Stacken jön létre az objektum Automatikusan foglalódik neki hely a memóriában Automatikusan szabadul fel a hely a blokk végén A nevével tudunk hivatkozni rá, nem kell pointer Mint C-ben a változóknál
Statikus példányosítás Pl. Kor k1; //default konstruktor hívódik meg Kor k2(5.0); //paraméteres konstruktort hívjuk meg //ha az m_dsugar adattag public, így érhető el cout << k1.m_dsugar; delete k1; // ez hiba, nem lehet felszabadítani
Dinamikus példányosítás Heapen jön létre new operátorral foglaljuk Egészen addig él, amíg a delete operátorral nem töröljük Törölni kötelező, különben bent ragad a memóriában! Pointerrel tudunk rá hivatkozni Mint C-ben a dinamikusan foglalt tömbökre
Dinamikus példányosítás Pl. Kor *k2 = new Kor(); //default konstruktor Kor *k3 = new Kor(4.0); //paraméteres konstruktor cout << k3->m_dsugar; //adattag elérés delete k3; //memória felszabadítás, kötelező megtenni
Osztályok implementálása Javaban egy osztályt egy fájlba tettünk mindenestől C++-ban szétválasztjuk az osztály deklarációját az implementációjától C-ben ezt csináltuk a függvényekkel a header fájlok segítségével Minden osztály két fájlba lesz szétosztva: Osztaly.h osztály deklaráció: adattagok, metódus fejlécek Osztaly.cpp metódusok implementációja