Objektorienterad programmering
för D2 m fl
onsdag 1 november 2006 kl 14:00 - 19:00 i L003
Hjälpmedel: | Inga hjälpmedel. |
Poängkrav: |
Maximal poäng är 40.
För betyget 3 respektive G krävs 20 poäng. |
Resultat: | Meddelas på kursens hemsida senast onsdag 22 november 2006. |
Visning: |
Måndag 27 november 2006 kl 12:00-12:30 i mitt rum (T2220).
Efter visningen kan tentor hämtas på expeditionen. |
Examinator och jourhavande: | Thomas Padron-McCarthy, telefon 070-7347013. |
För alla uppgifter på tentan gäller: Man får använda både standard-C++ (som till exempel har pekare som anges med * och objekt som skapas med new) och Microsofts dialekt C++/CLI (som till exempel har pekare som anges med ^ och objekt som skapas med gcnew). Man kan dock få poängavdrag om man blandar ihop dem på ett felaktigt sätt, till exempel om man skapar ett objekt med gcnew och sen pekar på det med en *-pekare. |
För att lagra de uppmätta mätvärdena skapar vi klassen Matvarde. Specifikationen för klassen, den så kallade klassdefinitionen, ser ut så här:
Medlemsvariabeln matvarde anger det uppmätta mätvärdet. Det finns inga negativa mätvärden.class Matvarde { private: float matvarde; float felgrans; public: Matvarde(float matvarde, float felgrans = 0.0); float get_matvarde(); float get_min(); float get_max(); }; // Matvarde
Tyvärr är givarna inte exakta, så det riktiga värdet kan skilja sig från vad vi mätte upp. Därför lagrar vi också en felgrans, som är felgränsen i procent av mätvärdet. Ett exempel är att om det uppmätta värdet är 30.0, och felgränsen är 20.0, så räknar man med att felet är högst 6.0, och att det riktiga värdet alltså ligger någonstans mellan 24.0 och 36.0. Det är de gränserna som ska returneras av funktionerna get_min och get_max.
Implementera konstruktorn och de övriga medlemsfunktionerna.
I den här och alla andra uppgifter på tentan gäller: Om du ska använda en klass, funktion eller liknande sak från en tidigare uppgift, behöver du inte skriva koden för den på nytt. Du får också använda den även om du inte gjort uppgiften där man skulle skriva den. |
En Datapunkt ska innehålla tre privata medlemsvariabler:
Följande medlemsfunktioner ska finnas:
Skriv specifikationen (klassdefinitionen) för klassen Datapunkt.
(Ett tips: Det finns inget krav på att datapunkterna i den länkade listan ska lagras i någon särskild ordning.)
a) (2p) Skriv specifikationen (klassdefinitionen) för klassen Sensor.
b) (1p) Implementera konstruktorn.
c) (2p) Implementera medlemsfunktionen ny_matpunkt.
d) (3p) Implementera medlemsfunktionen get_medel.
e) (1p) Skriv en main-funktion som skapar en sensor, lägger in tre mätvärden med hjälp av ny_matpunkt, och till sist skriver ut medelvärdet som fås från get_medel.
Man kan säga att varje Sensor-objekt "äger" en länkad lista av mätpunkter. Klassen Sensor har ingen destruktor. I en miljö utan skräpsamling, som standard-C++, skulle det kunna uppstå ett problem eftersom destruktorn saknas. Vilket?
b) (2p)
Implementera destruktorn.
(Om man använder en miljö som har skräpsamling, som C++/CLI, så behövs det egentligen inte någon destruktor, men skriv den i alla fall, som om det inte fanns någon skräpsamling.)
Du får själv bestämma vad filen ska heta, och om det ska vara en binärfil eller en textfil.
Tips: Funktionen rand ger ett slumpmässigt heltal mellan 0 och RAND_MAX. Med följande uttryck kan man räkna ut ett slumpmässigt flyttal mellan 0 och 100:
Inkludera filen cstdio för att deklarera funktionen rand och konstanten RAND_MAX.100.0 * rand() / RAND_MAX
Du kan anta att klassdefinitionen för klassen Sensor finns i filen Sensor.h, och så vidare med eventuella andra av dina klasser som du behöver.
Både vassa och runda saker har en virtuell medlemsfunktion peta, som simulerar vad som händer om man petar på saken. Vassa sakers peta-funktion skriver ut Aj!, och runda sakers peta-funktion skriver ut Rullerull!.
Så här ser klassdefinitionerna ut:
class VassSak { private: int vasshet; public: VassSak(int vasshet); virtual void peta(); }; class RundSak { private: double diameter; public: RundSak(double diameter); virtual void peta(); };
a) (1p)
Skriv klassdefinitionen för klassen Sax. En sax är vass, och ska därför ärva VassSak. En sax har inga särskilda egenskaper förutom vassheten. Konstruktorn ska ta vassheten som argument.
b) (1p)
Implementera konstruktorn för Sax.
c) (1p)
Skriv klassdefinitionen för klassen Boll. En boll är rund, och ska därför ärva RundSak. Förutom diametern har en boll också en studskoefficient, som är ett flyttal. Konstruktorn ska ta både diametern och studskoefficienten som argument. När man petar på en boll ska bollen inte rulla utan studsa, så Boll ska ha en egen peta-funktion.
d) (1p)
Implementera konstruktorn för Boll.
e) (1p)
Implementera peta-funktionen för Boll. Den ska skriva ut Studselistuds!.
f) (1p)
Skapa klassen Igelkott. En igelkott är både rund och vass, och ska därför ärva både RundSak och VassSak. Förutom de ärvda egenskaperna har den ett antal taggar, som är ett heltal. Konstruktorn ska ta igelkottens alla egenskaper som argument. Igelkotten har också en egen peta-funktion.
g) (1p)
Implementera konstruktorn för Igelkott.
h) (1p)
Implementera medlemsfunktionen peta för Igelkott. Den ska först anropa peta i VassSak, för att skriva ut Aj!, och sen ska den anropa peta i RundSak, för att skriva ut Rullerull!.
Ledning till alla deluppgifterna: Med följande main-funktion:
ska man få denna utmatning:int main() { VassSak* vs = new VassSak(10); RundSak* rs = new RundSak(1.8); Sax* s = new Sax(10); Boll* b = new Boll(10.0, 0.9); Igelkott* i = new Igelkott(17.0, 4, 10000); vs->peta(); rs->peta(); s->peta(); b->peta(); i->peta(); } Aj! Rullerull! Aj! Studselistuds! Aj! Rullerull! |
i) (1p) Vad blir utskrifterna om man i stället har följande main-funktion?
int main() { VassSak* vs1 = new Sax(10); VassSak* vs2 = new Igelkott(17.0, 4, 10000); RundSak* rs = new Igelkott(19.3, 5, 11000); vs1->peta(); vs2->peta(); rs->peta(); }