3. gyakorlat¶
Ismétlés¶
- osztály
- konstruktor
- inicializáló lista
- const method
Objektum orientált programozás II¶
Az előző anyagrészben megismert osztályokhoz kapcsolódó kibővített anyagrész következik. Ezek olyan elemek, melyek a kényelmesebb és kifejezőbb kódolást teszik lehetővé.
Default adattag értékek¶
C++11 óta itt is lehetőségünk van alapértelmezett értéket adni az adattagjainknak deklarációkor. Így megússzuk azt, hogy minden konstruktorban be kelljen állítani az adattagoknak értéket (ez főleg akkor jöhet jól, ha ugyanazt az értéket szeretnénk mindenhol beállítani, így ha mégis más alapértelmezett értéket szeretnénk beállítani, nem kell az összes konstruktort módosítani). Persze ettől még megtehetjük, ilyenkor a konstruktorban lévő érték felülírja az alapértelmezett értéket. Ez is ismerős lehet Javaból.
1 2 3 4 |
|
Default paraméter értékek¶
Az úgynevezett "boilerplate" (felesleges) kódsorok elkerülése érdekében, lehetőségünk van default paraméter értékeket is megadni a függvényeinknek. Ez akkor tud jól jönni, amikor nagyon hasonló függvényeket szeretnénk írni, amik csak a paraméterlistájukban különböznek (pl. ha nem adjuk meg a max. létszámot, akkor azt 25-nek veszi). Azért, hogy ne kelljen egy adott függvényt (a benne lévő potenciális hibával) annyiszor lemásolni, lehetőségünk van megadni a paramétereknek alapértelmezett értéket, amit a függvény fejlécében a paraméter neve után tehetjük meg egyenlőség jellel.
Ezzel kapcsolatban a legfontosabb szabály, hogy mindig csak és kizárólag az utolsó valamennyi paraméternek lehet alapértelmezett értéke. Ez persze nem zárja ki, hogy az utolsó összesnek legyen, de olyat nem lehet, hogy csak a 2. és 5. paraméternek adott alapértelmezett értéket. A default paraméterekkel kapcsolatos összes szabály itt érthető el.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Delegating konstruktor¶
Megeshet, hogy két konstruktor működése elég hasonló, egyik kicsit több/másabb mint egy másik. Szerencsére itt is lehetőségünk van a kódmásolás elkerülésére, és meghívhatjuk az egyik konstruktorból a másikat. Ez hasonló lesz az inicializáló listához, annyi különbséggel, hogy az adattagok inicializálása helyett egy másik konstruktort is meghívunk (de ilyenkor már nem inicializálhatunk adattagot a konstruktor inicializáló listában). Ehhez annyit kell tennünk, hogy kiírjuk az osztály nevét, majd zárójelek között a paramétereket (mintha egy egyszerű metódushívás lenne). Megjegyzés: az itt látott megoldással lehet majd az örökölt osztály konstruktorát is meghívni.
1 2 3 4 5 |
|
Default konstruktor szerepe¶
A konstruktor feladata az objektum inicializálása, általában a paraméterben kapott értékeket felhasználásával. Azonban a default konstruktor úgy inicializálja, hogy ,,nem kap'' paramétereket, amivel inicializálhatná az objektumot. Így kérdéses, hogy miért akarunk olyan lehetőséget biztosítani, hogy a konstruktor valamilyen ,,alapértelmezett'' értékkel inicializálja az objektumot (pl. a Hallgato
-t üres névvel és kóddal).
A Hallgato
osztályt pl. névvel és kóddal látjuk el, de készítünk egy konstruktort, mely egyiket sem állítja be.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Ez azért fontos, mert ha kiakarjuk bővíteni a Kurzus
osztályt úgy, hogy a feljelentkezett Hallgato
-kat egy tömbben tárolja, fordítási hibát kapnánk. Ha nem lenne default konstrukora a Hallgato
osztálynak, akkor a C-ben megszokott, egyszerű módon nem tudnánk belőle tömböt létrehozni (csak ha expliciten inicializálunk minden elemet)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Mikor egy tömböt létrehozunk pl. a Hallgato
osztályból, akkor a tömb elemek inicializálódnak. Nézzük meg, hogyan is iniciálizálunk egy objektumot! Természetesen a konstruktor által, azonban kérdéses, hogy milyen értékeket kellene megadnia a rendszernek. Természetesen nem tudja, hogy minek kellene ott szerepelnie, ezért hibát jelez. Azonban ha van default konstruktor, akkor tud olyan konstruktort hívni, melynek nem kell paramétert átadnia, így minden elem inicializálása a megadott módon lezajlik. Nulla paraméteres konstruktort akkor is hívhatunk, ha egy paraméteres konstruktor minden paraméterének van default értéke. Ez könnyedén ambiguous hívást okozhat!
A probléma abból származott, hogy a tömb elemeinek inicializálásakor nem tudta a rendszer kitalálni, hogy milyen értékekkel akartunk inicializálni. Ha ezt a problémát megszüntetjük, vagyis megadjuk a várt értékeket, akkor default konstruktor nélkül is létrehozhatunk tömböt. Ekkor azonban minden elemet egyesével inicializálnunk kell.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Mivel tömböt a {} jelek között inicializálhatunk s egy-egy objektumot is inicializálhatunk a {} jelek között a fönti példában egyesével megadtuk, hogy mik legyenek a 0. és az 1. indexű elemek konstruktor hívásakor átadott paraméterek. Ez nem tanácsos, főleg ha több elemről beszélünk.
default metódus¶
Már volt szó a default konstruktorról. Ha nem írjuk ki, van default konstruktor, azonban ha már bármilyen másik konstruktort írunk, alapból nem lesz generált default konstruktor, ekkor meg kell írnunk magunknak. Ha már egy üres konstruktort írunk, kérdéses lehet, hogy az default akar lenni, vagy elfelejtettük megírni. Ha a default kulcsszót használjuk, rövidebb és olvashatóbb kódot kapunk.
1 2 3 4 5 6 7 8 9 10 11 |
|
deleted metódus¶
Sokszor kell bizonyos dolgokat megtiltanunk a felhasználónak. C++ esetében ezt egy osztályra a deleted metódussal tehetjük meg.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Otthoni gyakorló feladatok¶
- Írjunk egy osztályt, amely egy Kurzust reprezentál.
- A Kurzusnak van neve (
string
típusú), kódja (string
) és maximális létszám, hogy hány hallgató veheti fel. - Ne legyenek publikusak az adattagok, de legyen hozzájuk getter metódus.
- Az osztálynak legyen egy konstruktora, ahol megadhatjuk a jellemzőket és a konstruktor inicializálja ezeket.
- Legyen egy
main
függvény is, ami bekéri a kurzus adatait, majd létrehozza azt, és kiírja a kurzus jellemzőit. - Megoldás
- A Kurzusnak van neve (
- A konstruktor paramétereinek a neve egyezzen meg az adattagok neveivel, és a this segítségével inicializáljuk az adattagokat.
- Default paraméter segítségével valósítsuk meg, hogy ha nem adják meg a max. létszámot, akkor az legyen 25.
- Megoldás
- Konstruktor inicializáló lista segítségével inicializáljuk az osztály adattagjait. Legyen 2 konstruktora az osztálynak (function overload), ahol a második esetében nem kell megadni a max. létszámot, és azt 25-re állítja. Megoldás.
- Inicializáljuk a maximális létszámot default inicializáció segítségével. Megoldás.
- A két konstruktor "működése" azonos, azért a 2 paraméteres konstruktor "hívja meg" a másik konstruktort (delegating konstruktor). Megoldás.
- Írjunk egy függvényt (ebben a példában ne a
Kurzus
osztály metódusa legyen), amelyik paraméterként (pointer) megkapja a kurzust, majd beolvas egy egész számot, és ennyivel megváltoztatja a kurzus max. létszámát. Ehhez aKurzus
osztályt is egészítsük ki a szükséges metódussal. Megoldás. - Valósítsuk meg a 6. feladatban szereplő függvényt referencia segítségével. Megoldás.