CD5250 - Objektorienterad programutveckling med C++, 5 poäng, period 4, 2001

Laboration 5

A. multipelt arv

I en tidigare laboration skapade ni klassen Klockradio som ärvde från både Klocka och Radio genom att använda multipelt arv. Om båda överklasserna i sin tur skulle ärva från en gemensam klass innebär det att underklassen kommer att få dubbla instanser av data definierat i den gemensamma överklassen.

  • Ett sätt att lösa detta problem är att använda sig av virtuellt arv. Beskriv vad som händer när ett objekt ärver virtuellt.
  • Ett annat sätt är att göra en rent abstrakt överklass som Klocka och Radio ärver från. Hur går detta till. Vilka krav ställs på klasserna Klocka och Radio när Klockradio skall ärva från bägge klasserna?
  • Lämna in en utförlig beskrivning och förklaring av frågeställningarna ovan.

    B. abstrakt överklass

    Implementera en "grafisk" editor där man kan skapa och hantera objekt av klasserna Circle, Line och Rectangle.


  • Klasserna Circle, Line och Rectangle skall ha metoder för att skriva ut och beräkna arean av objekten.
  • Gemensamma beteenden skall samlas upp i den abstrakta överklassen klassen Shape (enligt bilden ovan) så att polymorfism genom dynamisk bindning kan erhållas (dvs. man skall kunna hantera objekten på samma sätt utan att veta om det är en cirkel, linje eller rektangel).
  • Lägg t.ex. en rent virtuell metod Draw i klassen Shape samt implementera Draw metoder i alla underklasserna som vet hur respektive figur skall skrivas. T.ex. skulle tre olika objekt kunna skrivas ut så här:
  • Gul linje med ändpunkterna (55, 38) och (20, 72)
    Blå cirkel med centrum i position (115, 75) och radien 18
    Grön rektangel med hörnen i position (80, 25) och (90, 50)
    Exempel 1.

    Använd gärna klasserna ni gjort i en tidigare laboration (Line, Rectangle, Circle)

    C. behållare

    Utöka er "grafiska" editor med en behållarklass (Container) som kan hålla reda på alla objekt. Använd gärna stl::vector eller någon annan passande klass för att bygga upp er behållare.

  • Det skall finnas en metod för att skriva ut samtliga objekten i behållaren. Detta görs t.ex. genom att skapa en metod draw även i behållarklassen som går igenom alla shape-objekt och utför draw på vart och ett av dem.
  • Det skall finnas en metod i behållaren för att beräkna arean av samtliga objekt i behållaren.
  • D. filhantering

    Komplettera din editor ovan med filhantering så att dina "ritningar" kan lagras på respektive hämtas in från en valfri fil. Att spara figurerna på en fil är ganska enkelt, gör precis som med draw och area. Lagra exempelvis informationen på följande textbaserade filformat:

    Gul 55 38 20 72
    Blå 115 75 18
    Grön 80 25 90 50
    Exempel 2.

    Att hämta figurerna från en fil är något trassligare eftersom det då inte går att använda dynamisk bindning för att rätt load-metod skall väljas i och med att objekternas typer inte finns lagrade på filen. För att göra detta måste man även lagra någon typ av identifiering i filen:

    Förändra metoderna save så att de t.ex. skriver ut tecknen 'L', 'C' och 'R' för att markera objektens typ:

    L Gul 55 38 20 72
    C Blå 115 75 18
    R Grön 80 25 90 50
    Exempel 3.

    Vid inläsningen kan man nu läsa första tecknet i en rad och sedan utifrån detta skapa rätt typ av objekt:

    Shape * shapePtr;
    instream >> tag;
    switch (tag)
    {
       case 'L':
          shapePtr = new Line;
          break;
       case 'C':
          shapePtr = new Circle;
          break;
       case 'R':
          shapePtr = new Rectangle;
          break;
    }
    Exempel 4.

    Därefter är det bara att köra på som vanligt eftersom pekarvariabeln shapePtr nu pekar ut rätt sorts objekt och rätt load-metod därmed kommer att utföras (förutsatt att den deklarerats som virtual i klassen Shape).

    shapePtr->load();
    Exempel 5.

    Observera att behållarklassen inte skall lägga in någon som helst information om vilka typer av objekt som finns i behållaren. Behållaren skall inte veta om att det finns andra objekt än "Shape".

    Detta kan t.ex. lösas genom att man i behållarklassens load-funktion anropar en medlemsfunktion i klassen Shape (måste vara en statisk medlemsfunktion eftersom inget objekt har skapats ännu) som:

  • Utför switchsatsen ovan och skapar ett objekt av rätt sort.
  • Och sedan anropar load funktionen i rätt underklass.
  • Som slutligen returnerar det skapade objektet till List klassens load funktion som stoppar in objektet i listan.
  • E. snurr

    Snurra runt ett varv och klappa händerna. Laboration 5 är färdig, och ni har lärt er tillräckligt mycket C++ för att göra riktigt avancerade program.

    CD5250
    Nyheter
    Kursinformation
    Föreläsningar
    Labbar
    Projektuppgift
    Redovisningar
    STL-intro
    Size-klassen
    Visual C++
    Kursplan
    Schema
    Aktuellt
    Projektuppgift
    Föreläsning 7
    Laboration 6
    Underrubriker
    multipelt arv
    abstrakt överklass
    behållare
    filhantering
    snurr
    Ansvarig lärare: Martin Skogevall - martin.skogevall@mdh.se
    Senast uppdaterad: Wed May 16 21:18:24 GMT+02:00 2001