Sparsam lösningsskiss tenta Fredag 14 januari 2005 1.
a) Vad skriver följande kod ut?
A: A konstrueras, a\_=ap B: B konstrueras, b\_=ap B: --- B: B destrueras, b\_=ap A: A destrueras, a\_=ap A: A konstrueras, a\_=b B: B konstrueras, b\_=b B: --- B: B destrueras, b\_=b A: A destrueras, a\_=b
b) Vilken skillnad skulle det bli om alla virtual togs bort? (Ange bara änd- ringarna inte hela den nya utskriften, motivera)
A: A konstrueras, a\_=ap B: B konstrueras, b\_=ap
A: --- // A-delens println körs
A: A destrueras, a\_=ap // B-delens konstrukotr anropas inte A: A konstrueras, a\_=b
B: B konstrueras, b\_=b B: --- B: B destrueras, b\_=b A: A destrueras, a\_=b
c) Förklara när och varför det är viktigt med virtuella destruktorer? Spelar det någon roll i det här exemplet? Motivera.
2. sumElems summerar element i ett givet intervall i en vektor.
template<class T>
int sumElems(T it1, T it2) {
int ret = 0;
for (T t = it1; t != it2; ++t) ret += *t;
return ret;
}
a) Vilka krav ställer sumElems på indata?
Iteratorer som inparametrar. Det iteratorerna pekar på kan summeras till en int ret += *t;
1
b) Beskriv hur sumElems kan förbättras och göras mer generell?
Man kan få sumElems att summera godtyckliga argument och inte bara heltal.
c) Implementera ditt förslag.
T.ex. så här:
template<class S, class T>
S sumElems(S ret, T it1, T it2) {
for(T t = it1; t != it2; ++t) ret += *t;
return ret;
}
d) Vilka krav ställer din förbättrade version på indata?
Iteratorer som inparametrar. Det iteratorerna pekar på måste ha opera- tor+=
3.
a) Vad är en funktor? Vad är det för skillnad på en funktor och en funktion- spekare? Hitta på ett exempel där en funktor skulle vara mer användbar än en funktionspekare. Motivera.
En funktor är ett objekt som med operator() kan härma en funktionspe- kare. Eftersom det är ett objekt kan man spara tillstånd mellan anropen till skillnad från funktionspekare. Exempel en funktions som räknar rätt enbart varannan gång eller tar betalt efter 10:e anropet ..
b) Beskriv de implicit givna konstruktorerna defaultkonstruktor och kopie- ringskonstruktor. Hur fungerar de? När används de?
Se lösning till 2002-10-22
c) Varför är det viktigt att skriva en kopieringskonstruktor om klassen han- terar dynamiskt minne? Vilka andra metoder bör i så fall finnas med?
För att annars kopieras pekare enbart bitvis och man får pekare som pekar på samma minnesområde (förklaras utförligare i föreläsningsanteckningar- na). Förutom konstruktorerna bör man titta på destructorn och operator=
2
4. Det här talet handlar om när man får anropa protected-metoder. I java betyder protected både protected och paketprivat. Alla klasser i samma paket kan anropa alla andras protected metoder. Lägger man javaklasserna i olika paket fungerar det som i C++ nämligen enbart barnen får anropa sin förälders metod. OBS, man får inte anropa en annan instans förälder.
De metoder som kompilerar och man inte nämnt får också man poäng för.
Jag har klippt in kompilatormeddelanden i koden nedan using namespace std;
class A { public:
A(string s) : a_(s) { } // OK
void f1(A a) { cout << "f1: " << a.a_ << endl; } protected:
void f2(A a) { cout << "f2: " << a.a_ << endl; } string a_;
};
class B : public A { public:
B(string s) : A("base class"), b_(s) { } // OK void f3(A a) { cout << "f3: " << a.a_ << endl; } void f4(B b) { cout << "f4: " << b.b_ << endl; } void f5(A a) { cout << "f5: "; a.f1(*this); } void f6(A a) { cout << "f6: "; a.f2(*this); }
void f7(B b) { cout << "f7: " << this->a_ << endl; } void f8(B b) { cout << "f8: " << this->b_ << endl; } protected:
string b_;
};
int main() { A a("a");
A *ap = new B("ap");
B b("b");
a.f1(*ap); // tal3.cpp: In member function ‘void B::f3(A)’:
a.f2(*ap); // tal3.cpp:11: error: ‘std::string A::a\_’ is protected b.f2(a); // tal3.cpp:17: error: within this context
b.f3(a); // tal3.cpp: In member function ‘void B::f6(A)’:
b.f4(b); // tal3.cpp:10: error: ‘void A::f2(A)’ is protected b.f5(a); // tal3.cpp:20: error: within this context
b.f6(b); // tal3.cpp: In function ‘int main()’:
b.f7(b); // tal3.cpp:10: error: ‘void A::f2(A)’ is protected b.f8(b); // tal3.cpp:33: error: within this context
delete ap; // tal3.cpp:10: error: ‘void A::f2(A)’ is protected return 0; // tal3.cpp:34: error: within this context
};
3