Útmutató a 7.5 laborhoz

A laborfeladat az előadások és a laborok közötti csúszást hivatott kiegyenlíteni. Erre utal a 7.5 elnevezés.

Laborfeladatok megoldásokkal

A feladat célja az osztályokkal, örökléssel, a virtuális tagfüggvényekkel, valamint a heterogén kollekciókkal kapcsolatos ismeretek elmélyítése. A feladat a 7. laborfeladat síkidomokat modellező példáját bővíti tovább. A megoldás során fel kell használni a 7. laborfoglalkozáson elkészített Rajztabla osztályt.
A laborfoglalkozás végén 5 db fájlt kell feltöltenie — nagy részük már majdnem kész van — a Jporta rendszerbe (7.5 önellenőrző feladat), hogy megkapja a labor elvégzéséért járó pontot! Legalább az első öt tesztesetet (ELEKESZULT >= 5) hibátlanul meg kell oldania! A feladatok feltöltésére a laborgyakorlatot követő szombat 06:00-ig van lehetősége.

  1. Töltse le a laborgyakorlathoz előkészített projektet: https://git.ik.bme.hu/Prog2/labor_peldak/lab_07.5, ami a 7. laboralkalommal már megismert síkidomokat modellező példa módosított változata. Kezdetben a modell csak szakaszt, kört és rajztáblát tartalmaz, amit később bővíteni fogunk. Az új osztályok és funkciók kipróbálását a főprogramban definiált ELKESZULT makróval lehet vezérelni. A megértést segíti a mellékelt osztálydiagram:

  2. Első feladatként a modellt egy Poligon osztállyal bővítjük. A poligon első csúcsát és színét a konstruktorban kell megadni. Követelmény továbbá, hogy a poligonnak legyen
    • size() tagfüggvénye, amivel lekérdezhető, hogy hány csúcspontja van,
    • add() tagfüggvénye, amivel újabb pontot lehet adni a poligonhoz,
    • rajzol() tagfüggvénye, ami "kirajzolja" a poligont, azaz kiírja az adatait,
    • operator[]() tagfüggvénye, amivel lekérdezhető egy adott csúcspont.

    Legyen továbbá olyan globális insertere, amivel kiírathatók a poligon adatai a szakasznál és a háromszögnél is alkalmazott formához hasonlóan. Mivel a poligonnak tetszőleges számú csúcspontja lehet, a pontokat dinamikus memóriában fogjuk tárolni. A poligon.h fájlban elkészítettük az osztály deklarációját, ami még nem végleges. A dinamikus memóriaterület közvetlen használata miatt az implicit másoló konstruktor és értékadó operátor nem használható ezért ezeket is meg kell valósítani.
    Egészítse ki a poligon.h és poligon.cc fájlokat úgy, hogy az osztály az elvárásoknak megfelelően működjön! Megoldását több lépcsőben tesztelheti az ELKESZULT makró segítségével:

    • == 1 - Van Poligon osztály, amit önmagában kipróbál, de copy és assign még nincs használva;
    • >= 2 - Poligon assign-t is teszteli
    • >= 3 - Poligon assign-t és copy-t is teszteli
  3. A másoló konstruktor és az értékadás megvalósításakor ne felejtse el az alaposztály megfelelő tagfüggvényeit is meghívni, hogy az alaposztály adattagjai is inicializálódjanak. Ne módosítsa az alakzat.h fájlt!
    Célszerű a másoló konstruktor megvalósítását visszavezetni az értékadó operátorra! Fordítva is lehetséges, de a memtrace nem tudja kezelni a placement new-t, ezért most ezt ne próbálja ki!


  4. A 7. laboralkalommal elkészítette a Rajztabla osztályt. Emelje át megoldását ebbe a projektbe (rajztabla.h, rajztabla,cpp)! Fordítson és teszteljen! A keretprogram ELKESZULT==4 értéknél poligon nélkül fut, ELKESZULT==5 értéknél pedig poligonnal.
  5. A programunkban dinamikus memóriaterületen hozunk létre az alakzatokat, amelyekre pointerrel hivatkozunk. Ha egy pointerrel hivatkozott objektumról másolatot szeretnénk készíteni a dinamikus memóriában, akkor meg kell hívnunk a másoló konstruktorát valahogy így:
    	Szakasz*  pEredeti = new Szakasz(Pont(20,40), 100, 0, WHITE);
    	Szakasz*  pMasolat = new Szakasz(*pEredeti);
    

    Tegyük fel, hogy át szeretnénk másolni egy rajztábla objektumot egy másik rajztáblába. Ekkor nem elegendő a tárolt pointerek lemásolása, a benne tárolt alakzatokról is kell egy-egy másolat (deep copy), ahogy a poligon pontjait is le kellett másolnunk az első feladatban. Igen ám, de a rajztábla objektum alaposztályra mutató pointereket tárol, ezért nem tudjuk, hogy melyik alakzat másoló konstruktorát kell meghívni. Most lenne jó egy virtuális konstruktor, amit a ZH-ban többen fel szoktak találni, de sajnos a C++ nyelvben ilyen nincs. Helyette azonban bevezethetünk egy tagfüggvényt (pl. clone), ami már lehet virtuális és létrehoz egy másolatot saját magából a dinamikus memóriában. A clone használatával már egyszerű a másolat elkészítése. pl:

    	Alakzat*  pEredeti = new Szakasz(Pont(20,40), 100, 0, WHITE);
    	Alakzat*  pMasolat = pEredeti->clone();
    

    Módosítsa az alakzat.h fájt úgy, hogy legyen az Alakzat osztálynak egy tisztán virtuális konstans Alakzat* clone() tagfüggvénye is!

  6. Valósítsa meg a Szakasz osztály clone() tagfüggvényét a zzakasz.h fájlban! Állítsa az ELKESZULT makró értékét 6-ra! Fortdítson, teszteljen!
  7. Valósítsa meg a rajztábla értékadó operátorát és a másoló konstruktorát a clone() függvény felhasználásával! Állítsa az ELKESZULT makró értékét 7-re! Fortdítson, teszteljen!
    Célszerű a másoló konstruktor megvalósítását visszavezetni az értékadó operátorra! Fordítva is lehetséges, de a memtrace nem tudja kezelni a placement new-t, ezért most ezt ne próbálja ki!

  8. Legyen a poligon is klónozható! Állítsa az ELKESZULT makró értékét 8-ra! Fortdítson, teszteljen!
  9. Ha elégedett az eredménnyel, akkor töltse fel az elkészített illetve módosított poligon.h, poligon.cpp, szakasz.h, rajztabla.h, rajztabla.cpp fájlokat a Jporta rendszerbe (7.5 labor önellenőrző feladat), hogy megkapja a labor elvégzéséért járó pontot! Legalább ELKESZULT==5 szintig el kell jutnia.
    Amennyiben további feladatokat is megoldott, úgy feltöltés előtt a poligon.h fájlban definiálja a ELEKSZULT makrót!
    Hogy ne legyen gond a többszörös deifinicióból a lokális környezetében, célszerűen a definiciós rész így nézzen ki:
    #ifndef POLIGON_H
    #define POLIGON_H
    
    #undef ELKESZULT
    #define ELKESZULT   7  // A legnagyobb érték, amit szeretne, hogy a jporta teszteljen. 
    ...
    
  10. Valósítsa meg a Rajztabla osztályt a 7. előadáson bemutatott generikus tömb fixArray felhasználásával (https://git.ik.bme.hu/Prog2/eloadas_peldak/ea_07 gen_array2)! Ezt a tárolót a C tömbökkel azonos módon lehet indexelni, ezért a Rajztabla osztály deklarációjában és implementációjában csupán néhány sor változik:
    • Include-olni kell a sablont tartalmazó fájlt (gen_array2.hpp).
    • Változik a tabla tagváltozó deklarációja.

    A gen_array2.hpp fájlt már hozzáadtuk a projekthez, csak használnia kell! Megoldásának teszteléséhez állítsa az ELKESZULT makró értékét 9-re!

Jó munkát!

Szeberényi Imre

Utolsó frissítés: 2021-04-12 15.01