Size: 12037
Comment:
|
Size: 12090
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 13: | Line 13: |
das ist die Fehlermeldung | das ist die Fehlermeldung. P.S. was heisst diese & am Ende von ListOfIntegers? |
Fragen und Kommentare zur 5. Vorlesung / zum 5. Übungsblatt
Hallo, ich habe ein kleines Problem:
g++ -c ListProcessingMain.cpp ListProcessingMain.cpp: In function ‘int main(int, char**)’: ListProcessingMain.cpp:32: error: no matching function for call to ‘ListOfIntegers::interLeaveListOfIntegers( ListOfIntegers&, ListOfIntegers&)’ ./ListProcessing.h:30: note: candidates are: void ListOfIntegers::interLeaveListOfIntegers(int*, int*) make: *** [ListProcessingMain.o] Fehler 1 dario@ubuntu:~/Desktop/compito4$
das ist die Fehlermeldung. P.S. was heisst diese & am Ende von ListOfIntegers?
mein interleave funktion:
void interLeaveListOfIntegers(int* list1, int* list2);
und die Mainfunktion
... lista.interLeaveListOfIntegers(list1, list2); lista.printListOfIntegers("Result list : ");
ich verstehe nicht wie ich die Parameter anpassen soll.. list1 und list2 sind die zwei Objekten-elements (oder listen) die man aus char* erzeugt und haben schon eine definierte _size ohne Maxima.. Gruß
Dario 25Mai10 14:42
@Niklas: Ja, stimmt, schreiben Sie sich einfach eine get(int i) Funktion. Oder benutzen sie pop_back() wie von Sebastian vorgeschlagen, aber get wäre schon natürlicher. Eine dritte Alternative wäre in ListOfIntegers.h vor die Deklaration von parseFromString folgende Zeile zu schreiben
FRIEND_TEST(ListOfIntegersTest, parseFromString)
Das habe ich in der Vorlesung nicht erklärt, aber Sie dürfen es gerne benutzen, weil es eigentlich die Methode der Wahl ist. Damit geben Sie dem TEST(ListOfIntegersTest, parseFromString) die Rechte, auf die Membervariablen eines ListOfInteger Objektes zuzugreifen, insbesondere die _elements. Hannah 24Mai10 21:42
Das lässt sich mittels der pop_back Methode realisieren. SebastianD 24Mai10 16:47
Ok, noch eine Frage zu den Tests: Mir fällt irgendwie kein sinnvoller Test für die parse Funktion ein, der nicht die einzelnen Einträge der Liste anschauen muss. Dann bräuchte ich aber wieder eine Get() Funktion. Stehe ich da auf dem Schlauch oder ist das wirklich ein Problem? Niklas 24Mai 15:59
@Dario: Der constructor wird aufgerufen, wenn das Objekt deklariert und damit effektiv im Speicher erzeugt (konstruiert = constructed) wird. Aufgabe des Konstruktors ist es typischerweise, die Membervariablen des Objektes geeignet zu initialisieren. Der destructor wird aufgerufen, kurz bevor das Objekt aus dem Speicher gelöscht (zerstört = destructed) wird. Die Aufgabe des Destruktors ist typischerweise Aufräumen und schauen, dass aller Speicher der zu Lebzeiten des Objektes alloziert wurde auch wieder freigeben wird. Von daher schon nicht schlecht die Namen. Hannah 24Mai10 14:36
@Niklas: Erstmal keine Änderung gegenüber vorher, also ein TEST pro Methode und der heißt dann etwa TEST(ListOfIntegersTest, parseFromString). Hannah 24Mai10 14:32
Hallo, wenn ich das richtig verstanden habe werden Tests in Gtest ja so erstellt TEST(<Filename>, <Functionname>). Wie sieht das denn mit Klassen ordentlich aus? Checkt man da alle Funktionen in einem Test? Gruß Niklas 24Mai 14:18'
Also ich wollte nur eine kurze Frage stellen. Constructors und Deconstructors sind im Endeffekt nichts anders als Funktionen , die automatisch aufgerufen werden bzw. am Anfang der Klasse und eine am Ende der Klasse, wenn ich ein Objekt erstelle. Aber was wird "erzeugt und eliminiert"? Hätte nicht der Erfinder von c++ anders nennen können? Gruß Dario 23Mai 16:06
@Heinke: Nach dem Aufruf von parseFromString soll _size schon auf dem richtigen Wert stehen. Sie müssen den Wert da ja sowieso schon wissen, damit Sie, wie in der Aufgabenstellung gefordert, genau die richtige Menge Platz für den _elements pointer allozieren können. Wie Sie das machen, dafür gibt es viele Möglichkeiten. Eine davon ist, einfach vorab die Anzahl der Kommas im Argument listAsString zu zählen. Wenn das Argument eine korrekt formatierte Liste enthält ist die Anzahl der Elemente ja einfach die Anzahl der Kommas plus eins. Und wenn Sie beim Parsen der Liste herausfinden, dass Sie nicht korrekt formatiert ist, dann geben Sie den Platz einfach wieder frei und setzen size = 0, weil in dem Fall ja (nach wie vor) die leere Liste zurückgegeben werden soll. Eine andere Möglichkeit wäre, vorab einfach Platz für soviel ints zu reserviere wie das Argument listAsString lang ist (d.h. wieviele Zeichen es hat). Denn mehr Zahlen können ja nicht drin stehen. Am Ende vom Parsen wissen Sie ja dann wieviele ints tatsächlich drin standen und dann können Sie die genau passende Menge Platz allozieren und einmal umkopieren. So, das waren jetzt zwei Möglichkeiten, die mir spontan einfallen, aber es gibt bestimmt auch noch viele andere. Hannah 23Mai10 14:23
Kann ich einfach ne weitere Methode schreiben, die die Länge der Liste zurück gibt, die sie haben wird, wenn sie geparsed ist (also die orkommenden Zahlen zählt) und diesen Wert dann den Methoden für interleave und parse geben, damit _size entsprechend gesetzt wird? Oder gibts noch einen supergenialen Weg, der mir nur noch nicht eingefallen ist, weil ich nicht supergenial bin? Heinke 23Mai10 14:14
@Roman: Ja, richtig, kann praxisrelevant sein, muss aber nicht. Vielleicht kommen wir ja irgendwann gegen Ende des Semesters dazu. Freut mich auf jeden Fall, dass Sie sich für diese weiterführenden Konzepte interessieren und sich da offenbar auch schon sehr gut auskennen. Hannah 20Mai10 21:44
@Hannah: Ich wollte auf gar keinen Fall dogmatisch rüber kommen, aber als rein theoretisch würde ich gerade das KISS-Prinzip nicht sehen. Klassen die mehr als nur die essentiellen Eigenschaften/Methoden eines Objektes implementieren haben auf lange Sicht praxisrelevante Nachteile die mMn nicht vernachlässigbar sind, da die Klassen riesig werden und unintuitiv. Auch könnte man die getInterleaveOf Methode in der ListHandler Klasse abstrahieren und z.B. unabhängig von dem genauen Typ der Liste machen (z.B. per interface). Derjenige der seine interleaveWith Methode in der Liste selber implementiert kann diese Methode nun für jede andere Form von Listen kopieren (und bei irgendwelchen Änderungen ALLE Methoden ändern..). Dass das über den momentanten Stand in der Vorlesung hinausgeht is mir klar, aber die Praxis Relevanz sehe ich da trotzdem ganz deutlich. RomanW 20Mai10 21:32
@Roman: Mit "keine Methode ... sein sollte" und "ausgelagert sein sollte" wäre ich vorsichtig. Es gibt viele schöne Konzepte in der objekt-orientierten Welt, nur was die dann mit der Praxis zu tun haben, ist oft fraglich. Ich mache in der Vorlesung ganz dezidiert Programmieren in C++ aus der Praxis für die Praxis und so soll es sein und so soll es auch bleiben. Weiterführende Konzepte werden wir genau dann lernen und anwenden, wenn wir sie wirklich brauchen, vorher nicht. Hannah 20Mai10 21:07
@SebastianD: Die Konfusion kommt höchstwahrscheinlich daher, dass interleaveWith (imo!) streng genommen keine Methode der ListOfInteger Klasse sein sollte, sondern (gemäß dem KISS-Prinzip) in einer Art ListHandler Klasse ausgelagert sein sollte. Diese würde dann eine Methode a la ListOfIntegers getInterleaveOf(ListOfIntegers list1, ListOfIntegers list2) bereitstellen und die neue Liste zurückgeben. RomanW 20Mai10 20:53
@Ben: private bedeutet nicht Instanz-, sondern Klassensichtbarkeit. Du kannst also innerhalb deiner Listenklasse auf die (private) Member anderer Instanzen der Listenklasse zugreifen. SebastianD 20Mai10 20:19
@Hannah: Es ging mir prinzipiell nur um die Interleave Methode, da habe ich von außen keinerlei Zugriff auf die Listen in den übergebenen Objekten, da _size und _elements private ist. Somit muss man entweder get/set Methoden erstellen um die Werte einzelt auslesen zu können, die Klassenvariablen public machen oder die Methoden vom zweiten Teil nutzen (push_back/pop_back), wobei jedoch direkt bei der leeren Liste ein assert kommt, den ich nicht abfangen kann. Es war von mir weniger eine Frage sondern mehr eine Feststellung Ben 20Mai10 19:38
@Ben: Auf die Membervariablen _size und _elements brauchen Sie für dieses Übungsblatt keinen Zugriff von außerhalb der Klasse. Deswegen können Sie auch private sein (sollten Sie sowieso) und Sie brauchen auch keine spezielle get oder set Methode. Nur die Memberfunktionen brauchen Zugriff auf diese Membervariablen, und den haben Sie ja sowieso, d.h. Sie können z.B. in parseListOfIntegers einfach schreiben _size = listSize oder sowas. Hannah 20Mai10 19:28
@Heinke: Ja, genau, siehe mein code snippet in der Antwort an SebastianD. Hannah 20Mai10 19:23
@SebastianD: Berechtigte Frage. Ich würde es so machen:
void ListOfIntegers::getInterleaveOf(const ListOfIntegers& list1, const ListOfIntegers& list2);
und dann in der main Funktion:
ListOfInteger list1; ListOfInteger list2; list1.parseFromString(list1AsString); list2.parseFromString(list2AsString); list1.print("Input list 1 : "); list2.print("Input list 2 : "); ListOfInteger result; result.getInterleaveOf(list1, list2); result.print("Result list : ");
Die Version von Ben ist aber auch eine Variante die man in diesem Kontext öfter sieht. Ich würde die Methode dann allerdings interleaveWith nennen, man sollte das bei der objekt-orientierten Programmierung immer wie einen (einfachen) Satz lesen könnten. Die Variante hat halt den Nachteil, dass dann die eine Liste überschrieben wird, deswegen gefällt mir die oben besser. Hannah 20Mai10 19:14
@Hannah: Ah. Verstehe. Mit anderen Worten, ich muss also für jede Liste eine Instanz des Objektes erstellen. Oder sehe ichs immer noch falsch? Heinke 20Mai10 18:23
Für mich klingt es nach Version 1:
ListProcessing list1; [...] ListProcessing list2; [...] list1.interleave(list2); // Danach list1 ausgeben
Nur muss man sich dann imho Gedanken über die Sichtbarkeit von _size und _elements machen oder eine set/get Methode implementiern...Ben 20Mai10 17:36
Ich bin mir im Unklaren über die genaue Funktionsweise der neuen Interleave-Methode, da mir selbst spontan mehrere verschiedene Möglichkeiten einfallen:
1. void interleaveWith(ListOfIntegers list); // Die Elemente dieser Liste werden mit der Argumentliste vermischt (oder was auch immer).
2. ListOfIntegers interleaveWith(ListOfIntegers list); // siehe 1., nur dass die Argumente jetzt in einer neuen Liste gespeichert und diese zurück gegeben wird.
3. void interleave(ListOfIntegers list1, ListOfIntegers list2); // Speichert die Elemente der beiden Argumentlisten vermischt in dieser Liste (Liste vorher leeren?).
4. ListOfIntegers interleave(ListOfIntegers list1, ListOfIntegers list2); // Idealerweise sogar static. Speichert die Elemente der beiden Argumentlisten vermischt in einer neuen Liste und gibt diese zurück.
5. void interleaveWith(ListOfIntegers result, ListOfIntegers list); // C-Style. Man übergibt außerdem eine Liste, in der die Elemente dann gespeichert werden sollen.
6. ...
Welche davon? SebastianD 20Mai10 14:24
@Heinke: Für Aufgabe 1 vom neuen Übungsblatt soll das Programm exakt dasselbe machen, die Ihr Programm vom 4. Übungsblatt, nur soll das Programm mit Klassen realisiert sein, wie in der Vorlesung vorgemacht, und die Felder (die jetzt Membervariablen sind), sollen keine fixe Größe MAX_LIST_SIZE mehr haben, sondern genau die Größe, die benötigt wird. Beantwortet das Ihre Frage? Hannah 20Mai10 12:46
Verstehe ich das richtig: Der Benutzer soll ./ListProcessingMain "1,1,1,1" "2,2,2,2,2" aufrufen und anschließend sollen die Listen intern geparsed, interleaved und als array im Objekt gespeichert werden? Heinke 20Mai10 9:28