Útmutató a 4. laborhoz
A laborgyakorlaton a Jporta feladatban kiadott Resistor osztályt kell bővíteni. A laborfeladatokkal a 3. előadáson bemutatott alapértelmezett (implicit deklarált) tagfüggvények (konstruktorok, destruktor, értékadó operátor) szerepét és felhasználását gyakorolhatja.
A laborgyakorlat elvégzésének előfeltétele a Cpp Ellenállás nevű feladat sikeres megoldása.
Felkészülés a laborra
- Nézze át a 4. előadás anyagát, és példaanyagát!
- Ismételje át a 3. heti laborgyakorlat anyagát!
- Oldja meg a Jporta Cpp Ellenállás nevű feladatát
Laborfeladatok megoldásokkal
A laborfoglalkozás végén töltse fel az elkészített elkeszult.h és resistor.cpp fájlokat a Jporta rendszerbe (Resistor, ö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.
Előkészítés
- CPP Ellenállás feladat „beüzemelése”: Ehhez töltse le a laborfeladathoz előkészített összes fájlt a tárgy Git tárolójából: https://git.ik.bme.hu/Prog2/labor_peldak/lab_04! A letöltött projekthez adja hozzá a Ön megoldását, azaz másolja be a Jporta-n megoldott feladatából a resistor.cpp fájlt! Fordítsa le, próbálja ki! Ha nem sikerült hibátanul megoldania a Cpp Ellenallas feladatot, úgy kérje a laborvezető segítségét!
- Ha működik feladat, cserélje le a főprogramot a laborgyakorlathoz előkészített resistor_test2.cpp-vel! Az eredmények egyszerűbb ellenőrzéséhez ebben a változatban a korábban is bemutatott gtest_lite keretrendszert használjuk. Írja be az első tesztesetbe (999999 helyére) az Önnek kiadott CPP Ellenállás feladat specifikációja által megkövetelt ellenállásértéket! Fordítsa le a programot és futtassa. Ha mindent jól csinált, akkor 6 tesztnek kell futnia és nem lehet hiba (feltéve, ha megoldotta korábban a "CPP Ellenallas" Jporta fealdatot).
Feladatok
- A főprogramban (resistor_test2.cpp) keresse meg és jelölje meg megjegyzéssel azokat a sorokat, amelyek konstruktorokat (nem másoló) hívnak! A tesztesetek neve segít, de az is elképzelhető, hogy konstruktorhívás nem közvetlenül a resistor_teszt2.ccp fájlban van!
Ezután a resistor.cpp fájlban megvalósított konstruktorokat egészítse ki kiírásokkal, hogy ellenőrizhesse elgondolását! A paraméter nélkül hívható konstruktor írja ki a standard kimenetre, hogy "ctor0", az egyparaméteres pedig, hogy "ctor1"! A kiírásokhoz használja a
Pr() makrót! Az elkeszult.h fájlban állítsa az ELKESZULT makró értéket 1-re! Fordítson, futtasson! Egyik ablakban nyissa meg a főprogramot, ahova a kommenteket beírta, a másikban nézze a futás eredményét! Ezeket a kiírásokat várta? Ha nem, értse meg, hogy mi az eltérés oka! - Előadáson látta, hogy léteznek speciális tagfüggvények, amelyek implicit módon keletkeznek, ha azokat explicit módon nem deklarálják (alapértelmezett tagfüggvények). Egyik ilyen tagfüggvény a másoló konstruktor. A főprogramban keresse meg és jelölje meg megjegyzéssel azokat a sorokat, amelyek másoló konstruktort hívnak! Számolja meg, hány ilyen helyet talált!Tipp: A resistor.h fájlban megtalálja a másoló konstruktor deklarációját! Másolja azt át a resistor.cpp-be! Ügyeljen a helyes scope használatra!
Valósítsa meg a resistor.cpp fájlban a Resistor osztály másoló konstruktorát úgy, hogy az jól működjön és írja ki a standard kimenetre, hogy "copy"! A kiíráshoz használja a Pr() makrót! Ne felejtse el az adattag inicializálását, azaz a megfelelő másolat előállítását sem! Az explicit másoló konstruktor meghívja az adattagok másoló konstruktorát (inicializálja azokat).
A másoló konstruktor formálisan egy olyan konstruktor, aminek egyetlen, az osztályra hivatkozó const referencia paramétere van! Az adattag(ok) inicializálása formálisan helyesen csak inicializáló listán történhet (C++11 előtti változatokban). Egyéb esetben inicializálatlanul jönnek létre a tagváltozók, amit persze értékadással módosíthatunk, de így először létrejön a tagváltozó a paraméter nélkül hívható konstruktorral, majd ennek értéket adunk.Állítsa az ELKESZULT makró értéket 2-re! Fordítson, futtasson! Az előző feladathoz hasonlóan elemezze a kiírásokat! Célszerűen az egyik ablakban a forrást, a másik ablakban a futás eredményét nézze! Ezeket a kiírásokat várta? Ha nem, akkor
- Tegyen a töréspontot másolókonstruktorba és hajtsa végre a programot úgy, hogy a másolónál mindig álljon meg és nézze meg, hogy az honnan hívódott! (Debug --> Debuging windows --> Call stack)
- Kérje laborvezetője segítségét, ha önállóan nem jut előre!
- A főprogramban keresse meg és jelölje meg megjegyzéssel azokat a sorokat, amelyek destruktort hívnak! Valósítsa meg a resistor.cpp fájlban a Resistor osztály destruktorát, ami kiírja, hogy "dtor"! A kiírásokhoz használja a Pr() makrót! Állítsa az ELKESZULT makró értéket 3-ra! Fordítson, futtasson! Ezeket a kiírásokat várta?
- A főprogramban keresse meg és jelölje meg megjegyzéssel azokat a sorokat, amelyek értékadó operátort hívnak! Valósítsa meg a resistor.cpp fájlban a Resistor osztály értékadó operátorát úgy, hogy az helyesen működjön és írja ki, hogy "assign"! A kiírásokhoz használja a Pr() makrót! Állítsa az ELKESZULT makró értéket 4-re! Fordítson, futtasson! Ezeket a kiírásokat várta?
- Készítsen tagfüggvényt, melynek segítségével lekérdezhető az ellenálláson eső feszültség, illetve az átfolyó áram (getI(double),getU(double))! Állítsa az ELKESZULT makró értéket 5-re (getI()), majd 6-ra (getU())! Fordítson, futtasson!
- Bővítse az osztályt összehasonlító operátorral (==) ! Állítsa az ELKESZULT makró értéket 7-re! Fordítson, futtasson!
Ha az egyenlőségvizsgálat tesztje hibát jelzett, akkor nagy valószínűséggel elkövette azt a hibát, hogy két valós számot hasonlított össze == operátorral. Gondolja át az előző félévben a valós számok ábrázolásáról tanultakat! A glite_test.h fáj legvégén talál egy almostEQ sablont. Használja azt megoldásában! - Készítsen inserter (<<) operatort, amivel egy ellenállás kiírható egy std::ostream objektumra! Állítsa az ELKESZULT makró értéket 8-ra! Fordítson, futtasson!
- Vegyünk egy potmétert melynek a névleges ellenállása legyen R (a két végkivezetés között). Az egyik végpont és a középső pont között az ellenállás a névleges érték (R) 1%-a és 99%-a között változtatható a kezelőszerv forgatásával.
Modellezzük a potméter két végpontjának összekötésével létrejövő áramköri elem működését, amit úgy használunk, hogy a középkivezetést és az összekötött végpontokat kötjük be az áramkörbe. Valahogy így:
A végpontok összekötésével létrejövő elem (SimPoti) működése két párhuzamosan kötött változtatható ellenállással (R1, R2) modellezhető, azaz az eredő ellenállás R1 % R2, ahol:
% a korábban bevezetett párhuzamos kapcsolást jelenti,
R1 + R2 = R,
R1 = R*POS/100,
R2 = R*(100-POS)/100
POS - a kezelőszerv állása: 1..99
Tervezze meg, majd valósítsa meg a SimPoti osztályt! Legyen az osztálynak:- Konstruktora, amivel megadható a potméter névleges ellenállása! A konstruktor középre (50%) állítsa a potméter kezelőszervét!
- Legyen lekérdezhető a kezelőszerv aktuális állása!
- Legyenek olyan tagfüggvények (pre-inkremens, és post-dekremens operator), amivel a kezelőszerv állása 1-1%-kal növelhető ill. csökkenthető! A legkisebb állás 1, a legnagyobb 99 legyen!
- Legyen lekérdezhető a mindenkori eredő ellenállás
A megvalósításhoz használja fel a Resistor osztályt, de azt ne módosítsa!
Ajánlott lépések:- Cserélje le ismét a főprogramot! Az új főprogram a potmeter_teszt.cpp legyen! Adja hozzá a projekthez a potmeter.h, potmeter.cpp, console.h, console.cpp fájlokat.
- Tanulmányozza a potmeter.h fájlt, és készítse el a hiányzó tagfüggvényeket a potmeter.cpp fájlban!
- A tanulmányozza a potmeter_teszt.cpp fájl teszt- és használati eseteit! A fájlban pár egyszerű teszteset után egy interaktív részt is talál, amiben az ellenállást billentyűnyomásra változtatható nagyságú áram, ill. feszültséggenerátorra kötjük és kvázi-grafikusan kijelezzük a mért értékeket. A konzol ablak kezelését a console.cpp fájlban definált Console osztály végzi.
Elemezze a kiírásokat! Fontos, hogy pontosan értse, hogy melyik kírás miért jelent meg a képernyőn! A Resistor.osszeg tesztesetben pl. miért jelenik meg "copy"? Hol van abban másoló konstruktor hívás? Ha pontosan érti minden kiírás hátterét, kapcsolja azokat ki, hogy a további feladatok megoldásában ne zavarjanak! Fordítsa le újra az egész projektet (Rebuild)!
Szorgalmi feladatok
IMSC feladatok
Jó munkát!
Szeberényi Imre