C++ Klassen Frage
-
Von mir aus kannst loslegen mit den Kritisieren.
-
Mehr als oben in dem Codefetzen steht hast noch nicht?
CraftPlorer schrieb:
#include <iostream> using namespace std; struct Element{ int data; Element *prev; // warum heiszt das Ding prev? }; class myList{ private: Element *first; Element *last; public: myList(){ first = new Element; // warum hat eine leere Liste ein Element? last = first; first[0].data = 0; // brrr ... first->data !? } void push_back(int in){ last = new Element; last[0].data = in; // siehe oben. first[0].prev = this->last; // Nach push_back() ist die liste kaputt. Wohin zeigt last->prev? } void show(){ // eine funktion, die nur das letzte element ausgibt? cout << last[0].data << endl; // siehe oben. } };Warum dereferenzierst du immer mitm Indexoperator anstatt mit dem Dereferenzierungsoperator?
Warum hat das Ding keinen Destruktor?
Was ist anpush_back()kaputt. Wie geht's richtig?
Wie greifst auf den Wert desiten Listenelements zu? Lesend und schreibend? Mal ohne Iterator?
Plötzlich kommst d'rauf, du hättest gerne auch einemyListfürfloat- was tust?//edit: tagsoup ...
-
Willst du eine einfach verkettete Liste? Also da hab ich es so gelernt, dass man einen Kopfknoten und einen Endknoten hat, die beide keine Daten enthalten. Jeder Knoten speichert nur einen Zeiger zu seinem Nachfolger und einen Zeiger/Referenz zu den Daten. Wenn du willst kann ich ja mal meine Implementierung einer verketteten Liste posten, zwar noch ohne Templates, aber die sind dann ja ein Kinderspiel. So wie du das versuchst wird das keine Liste, sondern allerhöchstens ein C-Abklatsch mit bisschen new/delete.
-
Der Tobi schrieb:
Also da hab ich es so gelernt, dass man einen Kopfknoten und einen Endknoten hat, die beide keine Daten enthalten.
Wieso sollen Wurzel und Ende keine Daten tragen?
Der Tobi schrieb:
Jeder Knoten speichert nur einen Zeiger zu seinem Nachfolger und einen Zeiger/Referenz zu den Daten.
Warum "Zeiger/Referenz zu den Daten" und nicht gleich die Daten selbst?
Der Tobi schrieb:
Wenn du willst kann ich ja mal meine Implementierung einer verketteten Liste posten, [...] So wie du das versuchst wird das keine Liste, sondern allerhöchstens ein C-Abklatsch mit bisschen new/delete.
Zeig' mal.
-
Ist sicherlich in keiner Weise perfekt.
#include <iostream> #include "list.h" //main.cpp int main() { List list; for (int i = 0; i<1000; ++i) list.insert(i); list.print(); }//list.h #include "node.h" #include "startnode.h" #include "endnode.h" class List { Startnode* _start; List(const List&); List& operator=(const List&); public: List(); ~List(); void insert(const Data&); void print() const; };#include "list.h" #include <iostream> //list.cpp List::List() : _start(new Startnode(new Endnode)) { } List::~List() { delete _start; } void List::insert(const Data& dat) { _start->insert(dat); } void List::print() const { _start->print(); }//startnode.h #include "node.h" class Startnode : public bNode { bNode* _next; Startnode(const Startnode&); const Startnode& operator=(const Startnode&); public: Startnode(bNode*); ~Startnode(); bool insert(const Data&); void print() const {_next->print();} };#include "startnode.h" #include <iostream> //startnode.cpp Startnode::Startnode(bNode* next) : _next(next) { } Startnode::~Startnode() { delete _next; } bool Startnode::insert(const Data& dat) { if (!_next->insert(dat)) _next = new Node(dat, _next); return true; } const Startnode& Startnode::operator=(const Startnode& rhs) { *(this->_next) = *(rhs._next); return *this; }#include "data.h" class bNode { public: virtual ~bNode() {} virtual bool insert(const Data&) = 0; virtual void print() const = 0; }; //node.h class Node : public bNode { Data* _data; bNode* _next; const Node& operator=(const Node&); Node(const Node&); public: Node(const Data&, bNode*); ~Node(); bool insert(const Data&); void print() const; };#include "node.h" #include <iostream> //node.cpp Node::Node(const Data& dat, bNode* next) : _data(new Data(dat)), _next(next) { } Node::~Node() { delete _next; delete _data; } bool Node::insert(const Data& dat) { if (!_next->insert(dat)) //if insert returns false for the next node (can only happen if next node is _next = new Node(dat, _next); // end node, because Node::insert always returns true) insert is return true; //called for the next node -> all nodes are added directly before the end node } void Node::print() const { std::cout << "Wert: " << _data->Value() << "\n"; _next->print(); }//endnode.h #include "node.h" #include <iostream> class Endnode : public bNode { public: ~Endnode() {} bool insert(const Data& dat) {return false;} void print() const {} };//data.h class Data { int _value; public: Data(int = 0); ~Data(); Data(const Data&); const Data& operator=(const Data&); bool operator<(const Data&) const; bool operator==(const Data&) const; bool operator>(const Data&) const; void Value(int v) {_value = v;} int Value() const {return _value;} };#include "data.h" //data.cpp Data::Data(int val) : _value(val) { } Data::~Data() { } Data::Data(const Data& rhs) : _value(rhs._value) { } const Data& Data::operator=(const Data& rhs) { this->_value = rhs._value; return *this; } bool Data::operator<(const Data& rhs) const { return (this->_value < rhs._value); } bool Data::operator==(const Data& rhs) const { return (this->_value == rhs._value); } bool Data::operator>(const Data& rhs) const { return (this->_value > rhs._value); }Ja, jetzt wo ich es mir nochmal anschaue war die abstrakte Basisklasse doch irgendwie ein Overkill. Warte, ich setz mich nochmal ran.
-
Also das von Tobi versteh ich gar nicht...
Ich hab mich noch mal selber ran gesetzt und hab jetzt 3 Probleme.
1. Bei der Klasse it fehlt halt das first also das erste Element.
Könnte ich natürlich ganz einfach mit Parameter lösen aber kann man das nicht so machen das man die Klasse so erstellt das sie alle werte bekomme von einer andern also beim ersten erstellen(myList list; it It;) das man da angibt das It zu list gehört?2. Wie mach ich das das es nicht nur für int funktioniert? Ich meine wenn ich ein Pointer erstelle muss ich doch angeben von welchen Typ...
3. Ich bin mir ziemlich sicher das der Destructor falsch ist also das mit den löschen. Wie sieht das richtig aus?
Der Code:
#include <iostream> #include <conio.h> using namespace std; struct Element{ int data; Element *last; Element *next; }; class myList{ private: Element *current; Element *before; Element *first; Element *last; bool _New; public: myList(){ current = new Element; first = current; last = current; before = current; current->last = current; current->next = current; } ~myList(){ delete [] current; } void push_back(int in){ if(_New){ current->data = in; _New = false; } current = new Element; before->next = current; current->data = in; current->last = before; current->next = current; last = current; before = current; } void show(){ Element *loop; loop = first->next; cout << loop->data << " " << loop << " " << loop->last << " " << loop->next << endl << endl; do{ loop = loop->next; cout << loop->data << " " << loop << " " << loop->last << " " << loop->next << endl << endl; }while(!(loop == last)); } }; //class it{ // private: // Element *loop; // Element end; // // public: // void insert(int end){ // myList classList; // loop = classList.first; // for(int i = 0; i <= end; i++){ // loop = loop->next; // } // cout << loop->data << endl; // } // //}; int main(){ myList list; for(int i = 0; i <= 100; i++){ list.push_back(i); } list.show(); _getch(); return 0; }Wer Fehler oder Verbesserungen hat bitte mit Zitat oder Zeilennummer antworten.

Hoffe ihr könnt mir helfen.
-
#include <iostream> /* #include <conio.h> kein std c++ */ using namespace std; struct Element{ int data; Element *last; // wtf? Element *next; }; class myList{ private: Element *current; // -+ Element *before; // -+- wtf? Element *first; Element *last; bool _New; // <- what? wird auch nicht initialisiert ... public: myList( ) { current = new Element; first = current; // wtf? warum hat eine LEERE liste schon wieder ein Element? last = current; before = current; current->last = current; current->next = current; } ~myList() { delete [] current; // hast du current mit new[] erzeugt? wenn nein: wtf? } void push_back( int in ) { if( _New ) { l current->data = in; _New = false; } current = new Element; before->next = current; current->data = in; current->last = before; current->next = current; last = current; before = current; } void show() { Element *loop; loop = first->next; // warum ist first nicht das erste element? Warum initialisierst loop nicht direkt bei der Deklaration? cout << loop->data << " " << loop << " " << loop->last << " " << loop->next << endl << endl; // was, wenn first->next == nullptr? do { loop = loop->next; cout << loop->data << " " << loop << " " << loop->last << " " << loop->next << endl << endl; // was, wenn loop->next == nullptr? } while( !(loop == last) ); } }; int main() { myList list; for(int i = 0; i <= /* 100 */ 10 /* reicht auch */; i++){ list.push_back(i); } list.show(); myList other_list; other_list.show(); // <- ouch! other_list.push_back( 1 ); other_list.show(); // <- ouch! /* _getch(); kein std c++ */ cin.get(); // tut's auch. }Warum initialisierst du Klassenmember nicht?
Warum die Unmenge an Pointer?
Warum hat einElementeinen Pointer aufs Ende (last)?
Verabschiede dich bitte von der Idee, direkt in die List einen Zeiger auf ein "aktuelles" Element ( <- was das auch immer im Kontext einer Liste sein sollte) zu halten.vielleicht solltest du dir die Definition einer einfach verketteten Liste ansehen: Einfach verkettete Liste
// edit: Geschmacksmuster:
#include <iostream> class list_node_t { private: int value; list_node_t *next; public: list_node_t() : value(), next( nullptr ) {} list_node_t( int value ) : value( value ), next( nullptr ) {} int get_value() const { return value; } list_node_t* get_next() const { return next; } void set_next( list_node_t * const new_next ) { next = new_next; } private: list_node_t( list_node_t const &other ); // Unsere Listenknoten koennen nicht kopiert werden. }; class list_t { private: list_node_t *root; public: list_t() : root( nullptr ) {} ~list_t() { std::cout << "\n~list_t()\n"; if( root ) { // <- wenn das Ding nicht sowieso leer ist ... list_node_t *to_delete = root; list_node_t *next = nullptr; do { next = to_delete->get_next(); std::cout << "Deleting node with value " << to_delete->get_value() << "\n"; delete to_delete; } while( to_delete = next ); // solange next nicht nullptr } } void push_back( int value ) { std::cout << "\npush_back( " << value << " )\n"; if( !root ) { // sonderfall: Liste ist leer. std::cout << "Creating root node with value " << value << '\n'; root = new list_node_t( value ); } else { list_node_t *i = root; for( ; i->get_next(); i = i->get_next() ) { std::cout << "Passed node with value " << i->get_value() << '\n'; // Bis ans Ende laufen } std::cout << "Passed node with value " << i->get_value() << '\n'; std::cout << "Ceating new last node with value " << value << '\n'; i->set_next( new list_node_t( value ) ); // am letzen Element anhängen } } void print() const { std::cout << "\nprint()\n"; std::size_t counter = 1; for( list_node_t *i = root; i; i = i->get_next(), ++counter ) { std::cout << "List node #" << counter << " has value " << i->get_value() << '\n'; } } private: list_t( list_t const &other ); // Unsere Liste kann nicht kopiert werden. }; int main() { list_t list; for( int i = 1; i <= 5; ++i ) { list.push_back( i ); } list.print(); }Output:
push_back( 1 ) Creating root node with value 1 push_back( 2 ) Passed node with value 1 Ceating new last node with value 2 push_back( 3 ) Passed node with value 1 Passed node with value 2 Ceating new last node with value 3 push_back( 4 ) Passed node with value 1 Passed node with value 2 Passed node with value 3 Ceating new last node with value 4 push_back( 5 ) Passed node with value 1 Passed node with value 2 Passed node with value 3 Passed node with value 4 Ceating new last node with value 5 print() List node #1 has value 1 List node #2 has value 2 List node #3 has value 3 List node #4 has value 4 List node #5 has value 5 ~list_t() Deleting node with value 1 Deleting node with value 2 Deleting node with value 3 Deleting node with value 4 Deleting node with value 5// edit:
Reduziert aufs Wesentlichetemplate< typename T > class list_t { private: struct list_node_t { T value; list_node_t *next; list_node_t( T value ) : value( value ), next( nullptr ) {} } *root; list_t( list_t const & ); // not copyable. public: list_t() : root( nullptr ) {} ~list_t() { if( root ) { list_node_t *to_delete = root; list_node_t *next = nullptr; do { next = to_delete->next; delete to_delete; } while( to_delete = next ); } } void push_back( int value ) { if( !root ) { root = new list_node_t( value ); } else { list_node_t *i = root; for( ; i->next; i = i->next ); i->next = new list_node_t( value ); } } friend std::ostream& operator<<( std::ostream &os, list_t< T > const &list ) { std::size_t counter = 1; for( list_node_t *i = list.root; i; i = i->next, ++counter ) { os << "List node #" << counter << " has value " << i->value << '\n'; } return os; } };
-
Vielen Dank für deine Antwort.
Ich hab mir deine Kommentare bei meinen Quellcode mal angeschaut.
Das mit den wtf hat mir nicht viel gesagt und ich weiß hat nicht wie ich die weglassen soll oder was daran falsch ist.
Also ich glaub ich wollte so was wie doppelt verkettete Liste oder so machen also das ein Zeiger auf das vorige und einer auf das nächste Element zeigt.Der Code:
#include <iostream> using namespace std; struct Element{ int data; Element *prev; Element *next; }; class myList{ private: Element *current; Element *before; Element *first; Element *last; bool _New; public: myList(){ _New = true; current = nullptr; first = nullptr; last = nullptr; before = nullptr; } ~myList(){ //Hier bin ich mir nicht sicher ob alles gelöscht wird. if(!(first == nullptr)){ Element *loop = first; Element *to_delete = nullptr; while(!(loop->next == nullptr)){ to_delete = loop; loop = to_delete->next; delete to_delete; } } } void push_back(int in){ if(_New){ current = new Element; current->data = in; current->prev = nullptr; current->next = nullptr; first = current; last = current; before = current; _New = false; }else{ current = new Element; before->next = current; current->data = in; current->prev = before; current->next = nullptr; last = current; before = current; } } void show(){ Element *loop = first; if(!(loop == nullptr)){ Element *loop = first; cout << loop->data << " " << loop << " " << loop->prev << " " << loop->next << endl << endl; while(!(loop->next == nullptr)){ loop = loop->next; cout << loop->data << " " << loop << " " << loop->prev << " " << loop->next << endl << endl; } }else{ cout << "List empty!" << endl; } } }; int main(){ myList list; for(int i = 0; i <= 10; i++){ list.push_back(i); } list.show(); myList list2; list2.show(); list2.push_back(25155); list2.show(); list.show(); cin.get(); return 0; }Noch so ne Frage nebenbei kann man das hier im Forum auch so machen das man ein Text(Quellcode) ein und ausklappen kann also auf ein Button drückt und dann wird der erst angezeigt?
-
Wieso baust du dir überhaupt selbst eine verkettete Liste? Aufgabe für die Uni? Übungszwecke?
-
Ich mache das auch oft, da ich ungern etwas nutze was ich nicht selbst schon mal probiert habe(wenn es im Rahmen ist). Wenn wir alles nur noch fertige Libs und Engines nutzen, wer baut dann diese Libs/Engines?

Aber ich verstehe schon was du meinst, aber nur um Libs zu nutzen brauch man kein Studium zu machen. Außerdem sollte auch kein Informatiker nur Libs zusammen klatschen, dafür ist er einfach zu überqualifiziert. Diese Leute sollten z.B. eigenen Sprachen entwerfen, beraten, sehr große Projekte planen und nur ganz wenig selbst Hand anlegen. Ein Architekt käme auch nicht auf die Idee jetzt mit Zementkelle und Ziegelsteine hantieren zu wollen.
-
Ich mach das aus Übungszwecken um zu schauen was ich zum Thema Klassen und Pointer noch nicht kann...
Also falls was ich zuletzt gepostet habe ohne Fehler ist.
Würde ich mich freuen wenn mir jemand meine erste Frage beantwortet kann.