Templates (und eigene Container-Klasse inside)
-
class ListenElement{ private: T* item; ListenElement* next; public: ListenElement(); friend class Liste; }; class Liste{ private: ListenElement* first; ListenElement* current; public: Liste(); bool add(T*); //fügt neues Listenelement hinzu; T* wird in main() erzeugt bool remove();//löscht das Element aus der Liste, auf das current zeigt void begin(); //setzt current auf den Listenanfang(current=first) void next(); //setzt current auf das nächste Listenelement(current=current->next) T* getItem(); //liefert Pointer vom Typ T* von current->item };Hallo!
Oben habe ich eine verkettete Liste. Nun möchste ich natürlich, dass ich jedes beliebige von mir erzeugte Element in diese Liste einfügen kann.
Also müssen Tamplates ranhalten.
Die Frage ist nun, ob ich nur die Klasse ListenElement als Tamplate deklarieren kann, denn manche Funktionen aus Klasse Liste greiffen ja direkt auf T* aus ListenElement zu? Ich möchte nämlich nicht für jedes jeweilige Element eine neue Liste erstellen.
-
katzenmann schrieb:
Die Frage ist nun, ob ich nur die Klasse ListenElement als Tamplate deklarieren kann, denn manche Funktionen aus Klasse Liste greiffen ja direkt auf T* aus ListenElement zu?
Wie meinst du, manche Funktionen greifen direkt auf
T*zu? Sind sie von der jeweiligen Implementierung des verwendeten Typen abhängig?Falls ja, hast du etwas falsch designt. Ein Container hat nur die Aufgabe, mehrere Objekte gleichen Typs komfortabel und effizient zu verwalten. Er muss nichts über den Datentypen seiner Elemente wissen.
-
Nö, eigentlich funktioniert die Liste völlig unabhängig von ihren Elementen.
Aber mein Verständnis von Templates ist nicht gerade überragend.So sieht zB meine Fkt. add(T*) aus:
bool Liste::add(T *element){ ListenElement *tmp = new ListenElement(); if(tmp == NULL) return false; tmp->item = element; if(first == NULL){ first = tmp; return true; } else{ tmp->next = first->next; first->next = tmp; return true; } return false; }Ich komm nicht so ganz dahinter, wie es mit den Templates funktionieren soll, wenn nur die Klasse ListenElement als Template deklariert ist.
-
Beide Klassen müssen als Klassentemplates deklariert werden, damit sie mit beliebigen
Ts kompatibel sind. Zu Templates gibt es im Magazin dieses Forums einen guten Artikel, ich würde mir den mal anschauen.Ein paar Hinweise zu deinem Code:
// Wieso Rückgabetyp bool? Was kann schiefgehen? Fragst du den Rückgabewert // beim Aufruf auch ab? Wenn überhaupt, wären wohl Exceptions eher angebracht. bool Liste::add(T *element){ // Warum T* als Parameter -> eher const T& ListenElement *tmp = new ListenElement(); // Die folgende Abfrage bringt überhaupt nichts, da new im Fehlerfall // eine Exception wirft und nicht einen Nullzeiger zurückgibt. if(tmp == NULL) return false; // Du speicherst den übergebenen Zeiger direkt in die Liste? Möchtest du nicht, // dass die Elemente kopiert werden und in der Liste autonom verwaltet werden? tmp->item = element; if(first == NULL){ first = tmp; return true; // wie gesagt fragwürdig } else{ // Wäre das neue Element nicht so einzufügen, dass es danach an erster Stelle (oder // an letzter) steht? Aber die zweite Stelle scheint mir merkwürdig... tmp->next = first->next; first->next = tmp; return true; // ebenfalls fragwürdig } // Wann soll der folgende Code deiner Ansicht nach ausgeführt werden? return false; // aber da eh fragwürdig, einfach weglassen ;) }
-
Die Memberfunktionen müssen dann natürlich auch Template-Funktionen sein.
-
...für Nexus

-
FreakY<3Cpp schrieb:
Mehr brauchst du nicht um eine funktionierende Liste handzuhaben. Bei dir siehts nämlich ein wenig komisch aus.
Doch, es braucht mehr, wenn die Liste nützlich sein soll. Und komisch sieht es eher bei dir aus. Eine verkettete Liste unterstützt normalerweise keinen
operator[]. katzenmann hingegen hat in seinem Code bereits einen Iterator-ähnlichen Ansatz. Und dafür, dass er das Iterator-Konzept wahrscheinlich nicht kennt, ist das bereits recht intelligent.Und mehr braucht man natürlich, mindestens einen Destruktor, Kopierkonstruktor und Zuweisungsoperator. Aber wenn die Liste auch brauchbar sein soll, kommen noch Funktionen zur Löschung, Leerung, Einfügung und Grössenabfrage hinzu. Aber das nur nebenbei.
-
Nexus schrieb:
...
Hatte es mir selbst nochmal durchgelesen und es editiert

-
Trotzdem bleibt dein
operator[]ein schlechter Vorschlag. Zudem verbreitest du weiterhin Unwahrheiten.FreakY<3Cpp schrieb:
eig. nutzt man dafür keine 2 Klassen
In den meisten Listen-Implementierungen gibt es eine Klasse für ein Listenelement. Wie willst du sonst sinnvoll Zeiger auf andere Elemente speichern?
FreakY<3Cpp schrieb:
und wenn, dann steckt man meistens die eine in die andere.
Auch das muss nicht sein. Ist vielleicht nützlich wegen Information Hiding, aber ist nicht nötig. Für katzenmann ist es wohl eher verwirrend im Moment.
-
Nexus schrieb:
...
Meiner Meinung nach gehst du nach einem Sonderfall. Ich hab bisher die Listen meistens so in dem Prinzip gesehen. Wofür soll ich eine Klasse erstellen, wo auch eine Struktur langt. Außerdem, warum soll ich die Struktur nicht in die Klasse machen, wenn nicht noch eine andere Klasse auf die Struktur zugreift? Daher kann ich sie private in die Klasse machen...
-
FreakY<3Cpp schrieb:
Wofür soll ich eine Klasse erstellen, wo auch eine Struktur langt.
Strukturen sind Klassen. Davon bin ich ausgegangen, als ich deinen Post gelesen habe.
FreakY<3Cpp schrieb:
Außerdem, warum soll ich die Struktur nicht in die Klasse machen, wenn nicht noch eine andere Klasse auf die Struktur zugreift? Daher kann ich sie private in die Klasse machen...
Du weisst ja nicht, ob keine andere Klasse diese verwendet. Okay, es ist hier anzunehmen, später wäre es wohl auch zu empfehlen, da stimme ich dir zu. Aber wie angetönt scheint mir, als ob katzenmann zuerst noch Wichtigeres zu tun hätte.
