Högskolan Dalarna Objektorienterad Analys & Konstruktion, 10p 1 Övning 4. Arv och andra relationer Stegvis förfining som programutvecklingsmetodik Det är mycket viktigt att du jobbar stegvis när du utvecklar dina klasser. Börja med den enklaste konstruktorn någon enkel metod. Koda, kompilera och provkör. Gå sedan vidare och ta en metod i taget. I varje steg vet du då att om något blir fel, så måste det bero på det som du nyss har lagt till! 1. Designa en Person-klass som håller reda på ett namn och födelsedatum. Klassen Person ska ha två konstruktorer. - Person(char *name, int birthdate); - Person(); //Ska fråga efter namn och födelsedatum med hjälp av cout. Lägg till metoder för att skriva ut och beräkna vem som är äldst - const char *info(); // Returnerar en pekare till en textsträng med namnet och födelsedatum - void print(); // Skriver ut namnet och födelsedatumet med hjälp av info - bool isolderthen(person &enperson); // Returnerar "false" om enperson är äldre. Prova att skapa några objekt och anropa deras metoder. 2. Modifiera din klass så att den kan hålla reda på hur många personer som skapats i programmet. Skriv ut antalet innan du lämnar main(). Detta måste du lösa genom att i klassen införa ett attribut enligt följande, static int personcounter;. Glöm inte att initsiera din personräknare till 0. Det kan du göra i klassens definitionsfil med följande sats, int Person::PersonCounter = 0;. Lägg till en statisk medlemsfunktion som returnerar antalet personer. 3. Fråga om ett antal. Skapa sedan ett fält med Person-pekare av denna storlek. Loopa igenom och skapa varje objekt genom att dessa frågar om sina data. Skriv ut info om alla objekt. Sök sedan rätt på den yngsta och äldsta personen i fältet och skriv ut deras namn.
Högskolan Dalarna Objektorienterad Analys & Konstruktion, 10p 2 4. Designa och implementera klassen Familj. Ett objekt av typen Familj kan innehålla 0, 1, eller flera Personobjekt. Följande metoder ska ingå i klassen Familj. Familj(const char *efternamn); // Skapar ett familje-objekt med ett visst efternamn, men utan personer - Familj() // Skapar ett familje-objekt där efternamnet läses in med hjälp av // cin >>. Familj(const char *efternamn, Person medlemmar[]); // Skapar ett familje-objekt med ett visst efternamn och medlemmarna // tas från fältet medlemmar. void addmedlem(person &enperson); // Lägger till en medlem i familjen - const *char info(); // Returnerar en pekare till en textsträng med information om hela // familjen (all dess medlemmar) - void print(); // Se klassen Person - Person getmedlem(int i); // Returnerar en pekare till den i:te medlemmen i familjen, om den // finns. Om i är mindre än 0 eller större än antal medlemmar 1 // ska värdet 0 (NULL) returneras. int antalmedlemmar(); // Returnerar antalet medlemmar i familjen Skriv ett testprogram och skapa 2-3 familjer. 5. Modifiera din familjeklass så att du kan hålla reda på hur många familjer som skapats i programmet. Skriv ut antalet innan du lämnar main(). 6. Fråga efter ett antal. Skapa sedan en vektor med Familje-pekare av denna storlek. Loopa igenom och skapa varje objekt genom att dessa frågar om sina data. Skriv ut info om alla objekt. Loopa sedan igenom fältet och lägg till några personer här och var. Skriv sedan ut all information på nytt.
Högskolan Dalarna Objektorienterad Analys & Konstruktion, 10p 3 7. Designa och implementera en klasshierarki Fordon, LandFordon respektive VattenFordon, samt Bil, MotorCykel, och SegelBat. Deklarera klassen Fordon som en abstrakt basklass. Inför minst ett attribut per klass. Lägg till en metod const char *info() i varje klass. Denna ska returnera en beskrivande textsträng för objektet i fråga. Skapa några olika sorters fordonsobjekt och skriv ut information om dem. Använd gärna slumpning om du tycker det verkar tråkigt att hitta på variabelvärden. 8. Lägg till populationsräkning i Fordonsklassen, dvs räkning av hur många Fordonsobjekt som skapas. Skriv ut antalet skapade fordon i slutet av programmet. Notera att denna gång räknar vi fordon och inte antalet bilar eller motorcyklar. 9. Skriv en funktion skapafordon(), enligt nedanstående beskrivning: Fordon *skapafordon() switch(rand()%2) case 0: return new Bil( ABC123 ); case 1: return new MotorCykel( XYZ789 ); //Det här ska aldrig inträffa prova att anropa funktionen i main() enligt följande: Fordon *fordon[10]; for (int i=0; i<10; i++) fordon[i] = skapafordon(); for (i=0; i<10; i++) cout << fordon[i]->info(); 10. Modifiera klassen Person så att en person kan äga äga ett fordon. Lägg till metoder för att lägga till och ta bort ägarskap av fordon. Ändra också klassen Persons funktion info så att även info för eventuellt fordon anropas. 11. Konstruera en klassherarki för ytor. För varje typ av yta i klassherarkin ska det vara möjligt att beräkna ytans storlek. Skapa först en generell basklass Yta. Låt därefter klasserna Triangel, Rektangel och Cirkel ärva från basklassen Yta. Skapa även de båda klasserna LikbentTriangel och Kvadrat. Dessa båda klasser ska ärva av Triangel respektive Rektangel. Skriv ett program i vilket några ytor instanseras Låt dessa objekt skriva ut storleken på de ytor som de representerar.
Högskolan Dalarna Objektorienterad Analys & Konstruktion, 10p 4 12. Modifiera klasserna i föregående uppgift så att det blir möjligt att köra följande program. #include <stdlib.h> #include yta.h Yta *yta[10]=0; for (int i=0; i<10; i++) switch(rand()%5) case 0: yta[i] = Triangel(23, 25, 31); break; case 1: yta[i] = Rektangel(23, 14); break; case 2: yta[i] = Cirkel(19); break; case 3: yta[i] = Kvadrat(25); break; case 4: yta[i] = LikbentTriangel(17); break; for (i=0; i<10; i++) cout <<yta[i]->typavyta() << Area: <<yta[i]->area() <<endl; ; 13. Konstruera en klassherarki för volymer. För varje typ av volym i klassherarkin ska det vara möjligt att beräkna volymens storlek och volymens totala yta. Skapa först en generell basklass Volym. Låt därefter klasserna RatBlock och Cylinder ärva från basklassen Volym. Klassen RatBlock består av sex stycken objekt av typen Rektangel och klassen Cylinder består av två objekt av typen Cirkel och ett objekt av typen Rektangel. Utnyttja klassen Yta från föregående uppgift. Följande program ska vara möjligt att köra när de ovanstående klasserna fungerar som de ska. #include <stdlib.h> #include volym.h Volym *volym[5]=0; for (int i=0; i<5; i++) switch(rand()%2) case 0: volym[i] = RatBlock(23, 25, 31); break; case 1: volym[i] = Cylinder(23, 14); break; ; for (i=0; i<5; i++) cout << volym[i]->typavvolym(); cout << Volym: << volym[i]->volym(); cout << Area: << volym[i]->area() <<endl;
Högskolan Dalarna Objektorienterad Analys & Konstruktion, 10p 5 14. Du ska nu beskriva ett tågsätt med hjälp av C++. Längst fram i tåget skall ett lok finnas. Till loket skall det gå att koppla in vagnar i en följd efter varandra. Det ska även gå att koppla in en vagn mellan två vagnar och ta bort en godtycklig vagn i tåget. Loket ska vara en instans av klassen Locomotiv och vagnarna ska vara instanser av klassen Waggon. Loket skall kopplas till sin vagn genom att loket får tillgång till vagnens thispekare. Vagnen som är kopplad till loket skall i sin tur ha tillgång till den this-pekare som nästa vagn i tågsättet har och den vagnen ska ha tillgång till efterföljande vagns this-pekare och så vidare. Om någon pekare inte pekar på en vagn så skall den peka på NULL, dvs 0. Varje vagn ska dessutom ha en pekare till en textsträng i vilken vagnens destination specificeras. Du ska nu konstruera klasserna Locomotiv, Waggon, Train och ytterligare någon klass. Klassen Train ska innehålla en pekare till loket och en pekare som kan peka på någon av vagnarna eller loket. Train ska innehålla följande metoder: void gotothelocomotiv(); // Ställer vagnspekaren att peka på loket void gotonextwaggon(); // Flyttar vagnspekaren att peka på nästa vagn. Om den vagn som pekaren // pekar på nu är den sista vagnen så ska vagnspekaren tilldelas värdet // NULL, dvs 0. bool thebackend(); // Om vagnpekaren pekar på NULL så returneras true i annat fall // false bool emptytrain(); // Om loket inte har någon vagn kopplad efter sig, dvs om lokets pekare // pekar på NULL, så ska funktionen returnera true i annat fall // false char *inspectwaggon(); // Returnerar en pekare på den sträng som beskriver vagnens destination. void appendwaggon(wagon *waggonpek); // Kopplar in en ny vagn längst bak på tåget Waggon *removelastwaggon(); // Kopplar bort den sista vagnen i tåget void insertwaggon(wagon *waggonpek); // Sätter in en vagn efter den vagn som vagnspekaren pekar på. Waggon *removewaggon(); // Tar bort den vagn som vagnspekaren pekar på. Vagnspekaren pekar // därefter på föregående vagn eller loket. Skriv en main-funktion och provkör dina medlemsfunktioner eftersom du skapar dem. När du är klar med klasserna så kan du skriva ett litet program som flyttar om vagnarna mellan ett par tåg så att varje vagn hamnar i det tåg som går förbi vagnens destination.