DD2387 Programsystemkonstruktion med C++ Tentamen 2 Måndagen den 10 november 2014, 08:00-12:00 Introduktion Skriv dina svar på separata papper, dessa scannas in efter inlämning. Du kan skriva på båda sidor. Skriv namn och uppgiftsnummer på varje sida Grova fel ger underkänt, men gör ett försök på alla uppgifter Det är ingen självrättning efter tentan Hjälpmedel En, eller två, valfria läroböcker om C++. 1 Var annan fråga förekommer om vartannat Det diskuteras budgetfrågor i dessa dagar. Om ladorna är tomma eller inte och vilkas hjärtefrågor som måste med eller inte. Två politiska partier som bildat koalition vill få med sina hjärtefrågor i budgeten. De kommer överens om att varva sina hjärtefrågor i budgetpropositionen. Frågor a) Skriv en generisk funktion som givet en mängd politiska förslag (definierat av två iteratorer till en godtycklig förslagstyp) returnerar true om intervallet endast består av två olika typer av förslag samt att de kommer i varannan ordning, annars ska funktionen returnera false. A B A B A => true A B A B A B => true A B A B A C => false B A B A B => true A => false Gör inget off-by-one fel, och säkerställ att programmet inte kraschar om man skickar in en för liten (t.ex. tom) mängd. b) Vad ställer din kod för krav på iteratorerna (parametrarna)? 1
2 Den dynamiska budgeten Det kan vara bra att lägga fram ett dynamiskt budgetförslag om det parlamentsmajoriteten skulle kastas om inför omröstning. Förklara kortfattat vad dynamic_cast används till i C++. (Tips: se bok type conversion) 3 Hur budgeten lagras Budgeten är som en containerklass med diverse instoppade element. Man skulle kunna skapa sig en egen container-klass istället för att använda standardklasserna. a) Om vi väljer att implementera en container lik std::vector är det viktigt att inte alltid förlita sig på de automatiskt genererade medlems-funktionerna som kompilatorn skapar åt oss; varför? b) Vilka automatiskt genererade medlemsfunktioner brukar ingå i det som tidigare (C++98) kallades för "Rule Of Three"? 2
4 En oomkullrungelig const budget Praxis var att budgeten måste antas i sin helhet och man kunde inte bryta ut delar ur den. Den var så att säga read-only eller const-deklarerad. Förra året ändrades praxis med oklar laglig grund som i skrivande stund utreds av högsta förvaltningsdomstolen. Konstigt nog ska budgeten röstas igenom innan man vet vad som gäller. Att ha koll på const är viktigt i C++. struct Budgetitem { Budgetitem(string s) { //... ; class Proposition { std::vector<budgetitem> budget; public: bool vote() const { //... ; bool new_kind_of_vote(std::vector<budgetitem>::iterator unwanted_item) const { budget.erase(unwanted_item); void add(const Budgetitem & b) { b = Budgetitem("something we approve"); void add_copy(budgetitem b) { b = Budgetitem("something we approve"); //... constructors, methods etc // change b // change b a) Koden ovan genererar ett par kompileringsfel. Vad är det som är fel? b) Hur skulle man kunna ändra i klassen Proposition (utan att ta bort const) så att koden kompilerar? c) Kompilerar följande kod? int main() { Proposition p; Budgetitem b("endast förluster i välfärden"); const Budgetitem & important_item = b; p.add_copy(b); d) Varför bör man sträva efter att använda const där så är möjligt i C++? 3
5 Den amerikanska budgeten Den amerikanska budgeten ska klubbas igenom den närmsta tiden. Förra året var en riktigt rysare om budgetstupet skulle träda i kraft eller inte. I den virtuella verkligheten som kongressen lever i är det inte lätt att veta vartåt det pekar. Det är viktigt att ha koll på virtual och pekare i C++ #include <iostream> using namespace std; struct Bill { //... ; struct FundRaiser { FundRaiser() : soul (this) { ; virtual void vote(const Bill & b) { cout << "Money please" << endl; struct FundRaiser * soul; struct Politician : FundRaiser { virtual void vote(const Bill & b) { cout << "Possibly" << endl; ; struct Republican : Politician { virtual void vote(const Bill & b) { cout << "No" << endl; ; void persuade(politician p, Bill & b) { p.vote(b); p.soul -> vote(b); // OBS copy 4
int main() { Bill obamacare; Republican r; FundRaiser f = r; FundRaiser * fp = &r; r.vote(obamacare); f.vote(obamacare); cout << "----------" << endl; // rita rak linje f.soul -> vote(obamacare); fp -> vote(obamacare); cout << "----------" << endl; persuade(r, obamacare); cout << "----------" << endl; // rita rak linje // OBS två utskrifter // rita rak linje Politician * pp = dynamic_cast<politician *> (fp); persuade(* pp, obamacare); // OBS två utskrifter Frågor a) Vad skriver ovanstående program ut (11 rader varav tre raka linjer)? b) Hur många pekare skapas i programmet (pekare i eventuell virtuell tabell samt this-pekare räknas inte) c) Rita en minnesbild över hur variablerna r, f och parametern p ser ut under programmets gång. Rita och namnge även de pekare som förekommer. 5
6 Läckor till media Under budgetarbetet får man ibland läsa vad som kommer eller inte kommer att ingå däri. Det tycks vara en strategi att läcka lämpliga delar till media och det kanske är bra för dem som har svårt att minnas vad budgeten ska innehålla. Hur minnesläckor fungerar i C++ är viktigt att känna till. Skriv en funktion leak som läcker minne varje gång den anropas. Funktionen behöver inte göra något vettigt och kan ta valfritt antal parametrar och returnera valfri parameter. 7 Budgetens funktion Vad budgeten fyller för för funktion objektivt sätt och i vilket tillstånd den är i är viktigt. Det är också viktigt att känna till funktionsobjekt (function object) i C++. Skriv kod för ett funktionsobjekt som ändrar på minst en medlemsvariabel. 6