Tentamen EDAF30 Programmering i C++

Relevanta dokument
Tentamen EDAF30 Programmering i C++

Tentamen EDAF30 Programmering i C++

Tentamen C++-programmering

DD2387 Programsystemkonstruktion med C++ Tentamen 1 Torsdag 7 januari 2016, 14:00-18:00

Tentamen EDAF30 Programmering i C++

Innehåll. Pekare Exempel

Innehåll. Pekare Exempel

Programmering i C++ EDA623 Arv. EDA623 (Föreläsning 6) HT / 42

Tentamen EDAF30 Programmering i C++

Innehåll. 1 Kort om dynamisk polymorfism. 2 Arv i C++ 3 Multipelt arv. 4 Något om statisk polymorfism. class Container {

SP:PROG3 HT12 Tenta

Innehåll. 1 Funktionsmalllar. 2 Klassmallar. struct Name { string s; //... }; const Name & minimum ( const Name & a, const Name & b) { if(a.s < b.

Innehåll. Parametriserade typer. Klassmallar. Klassmallen Vektor Konstructor med std::initializer_list. Klassmallen Vektor Medlemsfunktioner

TDDC76 - Programmering och Datastrukturer

TENTAMEN CD5250. Objektorienterad programutveckling med C++, 5p. Datum: , Tid: 14:00-19:00

Objektorientering - Arv och polymorfi. Eric Elfving Institutionen för datavetenskap

Programmering i C++ EDA623 Objektorienterad programutveckling. EDA623 (Föreläsning 5) HT / 33

Tentamen i TDP004 Objektorienterad Programmering Lösningsförslag

Programsystem konstruktion med C++ (2D1387) Innehåll. övning 2 klasser och arv

DD2387 Programsystemkonstruktion med C++ Tentamen 2

Det finns många flaggor till g++,

Tentamen i TDP004 Objektorienterad Programmering Lösningsförslag

Tillämpad programmering

Innehåll. Introduktion till objektorientering. OOP (objektorienterad programmering) Objekt, instanser, klasser

Operatoröverlagring. endast operatorsymboler definierade i C++ kan överlagras = += -= *= /= %= ^= &= = <<= >>= < > <= >= ==!= && > ->*, [ ] ( )

TDDC76 - Programmering och Datastrukturer

Övriga byggstenar. Övriga byggstenar. Några tips under programutveckling. Beroenden Pekare till funktioner Typkonvertering

Innehåll. Konstruktorer vid arv Regler för basklassens konstruktor. Konstruktorer vid arv. Konstruktorer vid arv. Konstruktorer vid arv

Innehåll. Användardefinierade typer. Användardefinierade typer Kategorier. Konstruktorer. Konstruktorer Två sätt att skriva initiering av medlemmar

DD2387 Programsystemkonstruktion med C++ Tentamen 3 Onsdagen 7 januari, 14:00-18:00

TDIU01 Programmering i C++

Del3 Klassanvändning, operatorer och pekare Ämnesområden denna föreläsning:

Lektionsuppgifter. TDDI14 Objektorienterad programmering. Lektionsplanering Lektion Lektion Lektion

Innehåll. 1 Deklarationer, scope och livstid. 2 Användardefinierade typer. 4 Operatoröverlagring. 5 In- och utmatning. 6 namnrymder (namespace)

Kapitel 6 - Undantag

TDDI14 Objektorienterad programmering

Innehåll. 1 Deklarationer, scope och livstid. 2 Användardefinierade typer. 4 In- och utmatning. 5 Operatoröverlagring. 6 namnrymder (namespace)

Innehåll. Exceptionella händelser (exceptions, undantag ) Felhantering Tre nivåer av felhantering: Nivå 2: exceptions (eller returvärde)

Tentamen *:85/2I4123 C

DD2387 Programsystemkonstruktion med C++ Tentamen 1 Tisdagen den 28 oktober 2014, 08:00-12:00

Introduktion till arv

Tentamen. DD2385 Programutvecklingsteknik vt 2013 Onsdagen den 22 maj 2013 kl Hjälpmedel: penna, suddgummi, linjal

Programsystemkonstruktion med C++

grundläggande C++, funktioner m.m.

TDDC76 Programmering och datastrukturer

Kapitel 3. Synlighet. Kapitel 3 - Klassanvändning, operatorer och pekare. Synlighet

Innehåll. Resource handles. Resurshantering. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 7. Resurshantering, Felhantering

1 Klasser och objektorientering Vad är objektorientering?

Ett enkelt program i C++, hello.cpp. #include <iostream> int main() { std::cout << "Hello World\n"; return 0; } C++, Övning 1

TDIU01 - Programmering i C++, grundkurs

Övning 4. Arv och andra relationer

Synlighet. Namespace Scope-operatorn Klasser Vänner

TENTAMEN OOP

Generell (template) programmering. Effektiv C++ Slutliga tips Genomgång av gammal tenta. Daniel Aarno Allt som fungerar som x ÄR x

Innehåll. Pekaren this Självreferens. Klasser Resurshantering, representation. Överlagring av operatorer. Överlagring av operatorer

C++ Objektorientering - Klasser. Eric Elfving

Innehåll. Resurshantering. Resource handles. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 6. Resurshantering

Polymorfi. Objektorienterad och komponentbaserad programmering

Innehåll. Typomvandlingar (casting) Implicita Typomvandlingar. Typomvandlingar (casting) Implicita Typomvandlingar

Innehåll. 1 Typdeklarationer och typomvandling 2 Resurshantering. 3 Objektorientering, kort repetition. 4 Klasser

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

Nedan skapar vi klassen Person innehållande datamedlemmar för förnamn, efternamn, ålder, längd och vikt:

Dynamisk bindning och polymorfism

Det finns en referensbok (Java) hos vakten som du får gå fram och läsa men inte ta tillbaka till bänken.

TDDC76 - Programmering och Datastrukturer

Det objektorienterade synsättet. Objekt. Datorprogrammet kan uppfattas som en slags modell av den verklighet programmet skall samverka med.

Tentamen i Grundläggande programmering STS, åk 1 fredag

Programsystemkonstruktion med C++: Övning 2. Karl Palmskog september 2010

Tommy Färnqvist, IDA, Linköpings universitet

Tillämpad programmering

DD2387 Programsystemkonstruktion med C++ Tentamen 1 Tisdagen den 28 oktober 2014, 08:00-12:00

KLASSER. Inkapsling Abstrakt datatyp Public och private. Klassmedlemmar Datamedlemmar Exempel Funktionsmedlemmar

Inlämningsuppgift, EDAF30, 2018

Subklasser och arv Inledning till grafik (JFrame och JPanel). Något om interface. Objektorienterad programvaruutveckling GU (DIT011) Subklasser

Tentamen i Objektorienterad Programmering 5p, Au, D, Fri, Pr,

5 Arv och dynamisk bindning FIGUR

Innehåll. Typomvandlingar (casting) Implicita Typomvandlingar. Typomvandlingar (type casts) Explicita, namngivna typomvandlingar (C++-11)

TDIU20 - Objektorienterad programmering i c++ - föreläsning 6

Tentamen i DD2387 Programsystemkonstruktion med C++

1. Klass med en dynamiskt allokerad variabel, definitionsfilen-del Klass med en dynamiskt allokerad variabel, inkluderingsfilen.

Programmering i C++ EDA623 Mallar. EDA623 (Föreläsning 12) HT / 29

Högskolan Dalarna sid 1 av 5 Data-sektionen Hans-Edy Mårtensson

Tentamen. DD2385 Programutvecklingsteknik vt 2014 Måndagen den 2 juni 2014 kl Hjälpmedel: penna, suddgummi, linjal

TDP004. Minne och pekare. Eric Elfving Institutionen för datavetenskap

Tentamen i Programmering

Inlämningsuppgift, EDAF30, 2018

TDDC76 - Programmering och Datastrukturer

TDIU20 - Objektorienterad programmering i c++ - föreläsning 4

Minnestilldelning (allokering) och frigörande (avallokering) av minne

Vad är en klass? Övning 2. Konstruktorer. ffl copy-konstruktorn tar en instans av klassen som. ffl default-konstruktorn tar inga argument och kan

Tentamen, Algoritmer och datastrukturer

LÖSNINGSFÖRSLAG TILL Tentamen i objektorienterad programmering i C++ I

Inlämningsuppgift, EDAF30, 2016

Tentamen i TDP004 Objektorienterad Programmering Teoretisk del

Objektorienterad Programkonstruktion, DD1346. Tentamen , kl

Introduktion. Klasser. TDP004 Objektorienterad Programmering Fö 2 Objektorientering grunder

Innehåll. EDAf30: Programmering i C++, 7.5 hp. EDAf30: Programmering i C++, 7.5 hp Viktiga skillnader mot Java

2D1387 Programsystemkonstruktion med C++ Laboration 1: Grundläggande C++ 31 augusti 2005

DI-institutionen Sid 1 av 6 Hans-Edy Mårtensson Sten Sundin

TDIU01 - Programmering i C++, grundkurs

Transkript:

LUNDS TEKNISKA HÖGSKOLA 1(6) Institutionen för datavetenskap Tentamen EDAF30 Programmering i C++ 2016 01 11, 8.00 13.00 Hjälpmedel: En valfri C++-bok. OH-bilderna från föreläsningarna är inte tillåtna. Du ska i dina lösningar visa att du behärskar C++ och även att du kan använda C++ standardklasser och algoritmer. Rena C-lösningar på problem som med fördel kan lösas enligt mera objektorienterade principer, eller egen implementering av sådant som finns i standardbiblioteket, kan därför ge poängavdrag, även om de är korrekta. I bedömningen av en lösning kan även minneshantering beaktas där det är relevant. Om du använder saker ur standardbiblioteket i din kod, var tydlig med att du gör det. Använd fullt kvalificerade namn eller using-direktiv för de namn du använder. Uppgifterna ger preliminärt 9 + 10 + 7 + 15 + 9 = 50 poäng. För godkänt krävs preliminärt 25 poäng (betygsgränser 3/25, 4/33, 5/42). Observera att ordningsföljden eller poängantalet för uppgifterna inte nödvändigtvis avspeglar deras svårighet. 1. Klassen Foo har konstruktorer som är private, och i stället factory-funktioner som är public och static: class Foo static Foo* create() return new Foo(); static Foo* create(int i) return new Foo(i); static Foo* create(const Foo& foo) return new Foo(foo); int compute() const; //... Foo(); Foo(int i); Foo(const Foo& foo); //... ; a) Detta görs för att begränsa hur objekt av klassen Foo kan allokeras i minnet. Vilken är begränsningen? b) Vi vill använda klassen Foo i en klass Bar enligt följande: class Bar Bar(int i=0) :fi int compute() const return f.compute(); Foo f; ; men detta går inte, utan man får ett kompileringsfel. Vilket tillägg behöver man göra till definitionen av klassen Foo för att klassen Bar ska fungera? Du ska inte göra några ändringar av de givna deklarationerna. c) Antag att vi inte kan ändra klassen Foo. Ändra klassen Bar (från uppgift b) så att den fungerar med den ursprungliga klassen Foo. Den ändrade klassen Bar ska ha samma gränssnitt utåt, och det ska fortfarande gälla att ett Bar-objekt har ett Foo-objekt som initieras i konstruktorn Bar::Bar(int), och att Bar::compute anropar compute på detta Foo-objekt. Svara med den modifierade klassen Bar.

2(6) 2. Följande program är ett exempel på användning av en polymorf klass och dynamisk bindning. #include<iostream> #include<vector> #include<cstring> using std::cout; using std::endl; struct Foo Foo(int i) :xi ~Foo() =default; virtual int getx() const return x; virtual void print() const; int x; ; struct Bar :Foo Bar(int i, const char* c); ~Bar() delete[] s; const char* gets() const return s; void print() const override; char* s; ; void Foo::print() const cout << "Foo(" << getx() << ")" << endl; Bar::Bar(int i, const char* c) :Foo(i) auto len = strlen(c)+1; s = new char[len]; strncpy(s, c, len); void Bar::print() const cout << "Bar(" << getx() << ", " << gets() << ")" << endl; void test() std::vector<foo*> v; v.push_back(new Foo(12)); v.push_back(new Bar(16, "Kalle")); v.push_back(new Bar(22, "Anka")); v.push_back(new Foo(17)); for(auto e : v) e->print(); for(auto e : v) delete e; Fortsättning på nästa sida...

3(6) Programmet fungerar som förväntat; om man kör funktionen test() får man följande utskrift: Foo(12) Bar(16, Kalle) Bar(22, Anka) Foo(17) Tyvärr har programmet ett allvarligt fel: det läcker minne. Vid test med ett verktyg som letar efter minnesläckor fick man följande resultat: LEAK SUMMARY: definitely lost: 11 bytes in 2 blocks indirectly lost: 0 bytes in 0 blocks possibly lost: 0 bytes in 0 blocks a) Vad innebär en minnesläcka? b) Vad är felet i programmet och varför leder det till en minnesläcka när test() körs?? 3. Betrakta följande klasser och funktioner: struct Foo virtual void print() const std::cout << "Foo" << std::endl; ; struct Bar :Foo virtual void print() const override std::cout << "Bar" << std::endl; ; struct Qux :Bar virtual void print() const override std::cout << "Qux" << std::endl; ; void print1(const Foo* f) f->print(); void print2(const Foo& f) f.print(); void print3(foo f) f.print(); int main() Foo* a = new Bar; Bar& b = *new Qux; Bar c = *new Qux; print1(a); print1(&b); print1(&c); std::cout << std::endl; print2(*a); print2(b); print2(c); std::cout << std::endl; print3(*a); print3(b); print3(c); return 0; Programmet går att kompilera och köra utan exekveringsfel. Vad skrivs ut när main() exekveras?

4(6) 4. Vi har en klass som representerar personer: using std::string; class Person Person(string f, string l, string d) :fnamef,lnamel,birthdated Person(const Person&) =default; Person(Person&&) =default; Person& operator=(const Person&) =default; Person& operator=(person&&) =default; const string& get_first_name() const return fname; const string& get_last_name() const return lname; const string& get_birthdate() const return birthdate; string fname; string lname; string birthdate; ; Vi vill kunna sortera en sekvens av personer med hjälp av std::sort, både i bokstavsordning (på Efternamn, Förnamn) och i åldersordning, samt sortera både stigande (minst först) och fallande (störst först). Vi har definierat en abstrakt klass, Comparator, som ska hantera jämförelser av Personobjekt. Medlemsfunktionen comp betyder som vanligt relationen mindre än, men användaren kan välja om operator() för ett Comparator-objekt ska betyda mindre än eller större än: class Comparator Comparator(bool asc=true) :ascendingasc bool operator()(const Person& a, const Person& b) const; virtual bool comp(const Person& a, const Person& b) const =0; virtual ~Comparator() bool ascending; ; bool Comparator::operator()(const Person& a, const Person& b) const return ascending?comp(a,b):comp(b,a); Vi ska nu ge ett exempel på användning, i ett testprogram. #include<vector> #include<algorithm> void check(const Person& a, const Person& b) assert(a.get_first_name() == b.get_first_name()); assert(a.get_last_name() == b.get_last_name()); assert(a.get_birthdate() == b.get_birthdate()); void test() auto anders = Person("Anders", "Karlsson", "2001-11-30"); auto nisse = Person("Nisse", "Nilsson", "1984-01-03"); auto bengta = Person("Bengta", "Bengtsdotter", "1934-07-25"); auto gustav = Person("Gustav", "Karlsson", "1928-10-11"); std::vector<person> vanders,nisse,bengta,gustav; std::sort(v.begin(), v.end(), NameComparator); //namn, stigande check(v[0], bengta); check(v[1], anders); check(v[2], gustav); check(v[3], nisse); programmet fortsätter på nästa sida...

5(6) std::sort(v.begin(), v.end(), NameComparatorfalse); // namn, fallande check(v[0], nisse); check(v[1], gustav); check(v[2], anders); check(v[3], bengta); std::sort(v.begin(), v.end(), DateComparatortrue); // födelsedatum, stigande check(v[0], gustav); check(v[1], bengta); check(v[2], nisse); check(v[3], anders); std::sort(v.begin(), v.end(), DateComparatorfalse);// födelsedatum, fallande check(v[0], anders); check(v[1], nisse); check(v[2], bengta); check(v[3], gustav); a) Implementera NameComparator och DateComparator (subklasser till Comparator) så att detta testprogram fungerar utan fel. Svara med fullständig definition av klasserna, inklusive alla medlemsfunktioner. b) Komplettera programmet med det som krävs för att man ska kunna sortera en std::vector<person> på namn (stigande) enligt ovan utan att skicka med ett komparator-objekt, d v s med anropet std::sort(v.begin(), v.end()); Använd om möjligt din lösning till uppgift a) för att undvika duplicerad kod. Svara med de ändringar och tillägg (uttryckta som C++-kod) du behöver göra. c) Vi vill skriva om vårt testprogram för att undvika att explicit jämföra element för element. I stället för std::sort(v.begin(), v.end(), NameComparator); //namn, stigande - check(v[0], bengta); check(v[1], anders); check(v[2], gustav); check(v[3], nisse); vill vi kunna skriva std::sort(v.begin(), v.end(), NameComparator); //namn, stigande if(!check(v, std::vector<person>bengta, anders, gustav, nisse)) std::cout << "*** fel i namn, stigande" << std::endl; Skriv en ny funktion check, som går att använda enligt detta exempel. Du får definiera hjälpfunktioner om du behöver men använd om möjligt funktionalitet som redan finns i standardbiblioteket. Svara med funktionen check och eventuella hjälpfunktioner.

6(6) 5. Betrakta följande kod using std::vector; using std::string; using std::cout; using std::endl; template <typename C> void print_seq(const C& c) for(auto x:c) cout << x << " "; cout << endl; vector<string>* collect_with_initial(char c, std::istream& is) auto res = new vector<string>; string s; while(is >> s) if(s[0] == c) res->push_back(s); return res; void use1() std::stringstream ss"smurf nisse tomte sallad kakor"; auto strings = collect_with_initial('s', ss); print_seq(*strings); // använd pekarnotation delete strings; // kom ihåg delete Funktionen collect_with_initial läser strängar från en ström och samlar de strängar, som börjar på en given bokstav (parametern c), i en std::vector<string>. När man använder denna (t ex i use1), så måste man dels använda pekar-notation, och dels komma ihåg att göra delete på resultatet. Detta är ofta onödigt besvär. För att förenkla för användaren vill vi ändra så att man i stället kan använda funktionen som i use2() (där funktionsmallen print_seq är samma som ovan): void use2() std::stringstream ss"smurf nisse tomte sallad kakor"; auto strings = collect_with_initial('s', ss); print_seq(strings); Ändra funktionen collect_with_initial så att man i stället kan använda den som i use2. (Både use1 och use2 ska skriva ut smurf sallad.) Svara med en fullständig funktionsdefinition för den ändrade collect_with_initial.