Smart Pointer
-
Hallo,
ich versuche schon seit nen paar Stunden eine Liste (mit Knoten) zu realisieren, die mit Smart Pointer funktionieren soll..
da gibt glaub ich noch mehrere Fehler, aber im Moment häng ich bei
"smartptr.h:48: error: ‘void smartPointer::operator=(const smartPointer&)†is private"
klar könnt ich den Teil auch in den public Bereich vorrübergehen kopiern.. das will der Compiler aber auch nichthier mein Quellcode:
#ifndef _SMARTPTR_H #define _SMARTPTR_H #include <cassert> #include <iostream> using namespace std; class knoten { private: int info; knoten * next; public: int getInfo() { return info; } void setInfo(int i) { info = i; } knoten * getNext() { return next; } void setKnoten(knoten * p) { next = p; } knoten * get(void) { return this; } }; class smartPointer { public: smartPointer(knoten *p); virtual ~smartPointer(); knoten * operator->() const; knoten & operator*() const; smartPointer & operator=(knoten *p); operator bool() const; void loescheObjekt(); private: int Anzahl; knoten* ZeigerAufObjekt; void operator=(const smartPointer&); // p1 = p2; verbieten smartPointer(const smartPointer&); // Initialisierung mit smartPointer verbieten }; inline smartPointer::smartPointer(knoten *p = 0) { ZeigerAufObjekt = p; if (ZeigerAufObjekt != NULL) { Anzahl = 1; } else { Anzahl = 0; } } inline smartPointer::~smartPointer() { loescheObjekt(); // siehe unten } // Die Operatoren -> und * prüfen, ob sie auf ein Objekt verweisen; // wenn nicht wird Fehlermeldung ausgegeben inline knoten* smartPointer::operator->() const { assert(ZeigerAufObjekt); return ZeigerAufObjekt; } inline knoten& smartPointer::operator*() const { assert(ZeigerAufObjekt); return *ZeigerAufObjekt; } inline smartPointer& smartPointer::operator=(knoten* p) { assert(ZeigerAufObjekt == 0); // stellt sicher, dass nur ein freier // Zeiger verwendet wird; es kann also keine // verwitweten Objekte geben. ZeigerAufObjekt = p; return *this; } //inline knoten * smartPointer::operator=(const smartPointer&) { // Anzahl++; // return ZeigerAufObjekt; //} // Mit Hilfe dieses Typumwandlungsoperators wird ein Vergleichsoperator // definiert. Damit sind Abfragen möglich, die testen, ob ein smartPointer // auf ein Objekt zeigt oder nicht. inline smartPointer::operator bool() const { return bool(ZeigerAufObjekt); } inline void smartPointer::loescheObjekt() { delete ZeigerAufObjekt; ZeigerAufObjekt = 0; // neue Intialisierung } #endif /* _SMARTPTR_H */
main:
#include <iostream> #include <stdlib.h> #include "smartptr.h" using namespace std; class Liste { private: smartPointer sp_pos; // knoten *pos; smartPointer sp_pre_pos; // knoten *pre_pos; smartPointer sp_anfang; // knoten *anfang; void rek(knoten * p) { if (p->getNext() != NULL) { rek(p->getNext()); } cout << p->getInfo() << endl; } public: Liste() { sp_pos = NULL; sp_pre_pos = NULL; sp_anfang = NULL; } void ins(int x) { smartPointer sp(new knoten); // knoten *p = new knoten; // erzeuge neuen knoten sp->setInfo(x); // Infowert wird x sp->setKnoten(sp_pos->get()); // next wird initialisiert mit alten P.-Zeiger // es wird also VOR dem aktuellen Element eingefügt if (sp_anfang == NULL) // Leere Liste sp_anfang = sp; if (sp_pre_pos != NULL) // Positionszeiger hat einen Vorgänger sp_pre_pos->setKnoten(sp->get()); else // neues Element steht am Anfang sp_anfang = sp; sp_pos = sp; // Positionszeiger zeigt nun auf das neue Element } int get() { // liefere aktuelles Element return sp_pos->getInfo(); } void del() { // Aktuelles Element löschen if (sp_pos != NULL) { // P.-Zeiger steht nicht am Ende if (sp_pre_pos != NULL) // P.-Zeiger steht nicht am Anfang sp_pre_pos->setKnoten(sp_pos->getNext()); else sp_anfang = sp_pos->getNext(); // Anfang wird neu gesetzt // delete sp_pos; // Speicher aufräumen if (sp_pre_pos != NULL) sp_pos = sp_pre_pos->getNext(); // P.-Zeiger steht auf // ehemaligem Nachfolger else sp_pos = sp_anfang; // Pos-Zeige auf Anfang } } void reset() { // Positionszeiger an den Anfang setzen sp_pos = sp_anfang; sp_pre_pos = NULL; } void adv() { // Positionszeiger vorrücken if (sp_pos != NULL) { sp_pre_pos = sp_pos; sp_pos = sp_pos->getNext(); } } bool end() { // Ende erreicht? return (sp_pos == NULL); } void ausgeben() { rek(sp_anfang->get()); } }; int main(int argc, char** argv) { Liste l; l.ins(5); l.ins(4); l.ins(3); l.ins(2); l.ins(1); cout << l.get(); l.adv(); cout << l.get(); l.ausgeben(); return 0; }
-
Hi Xeddon,
was für eine Art smartpointer willst du denn proggn?
Da dein Code relativ lang ist, geh ich erstmal auf das ein, was wir beim
ersten Blick ins Auge fällt.void ins(int x) { smartPointer sp(new knoten); // knoten *p = new knoten; // erzeuge neuen knoten // ... sp_pos = sp; // Positionszeiger zeigt nun auf das neue Element }
Du erstellst hier einen Smartpointer auf dem Stack.
Am Ende versuchst dann diesen deinem Feld zuzuweisen, jedoch ist der Zuweisungsoperator nicht sichtbar.Wenn du ihn als public definierst, dann fehlt dir leider (wahrscheinlich) die
Implementierung davon, weswegen dein Linker dann meckert.Als erstes solltest du mal erklären, warum dein pointer smart ist
wegen der Zusatzinfos?
Wie soll denn ein Kopieren des Smart-Pointers behandelt werden?
-
hiho,
also beim Überfliegen ist mir mal das aufgefallen:
smartPointer sp_pos; // knoten *pos; smartPointer sp_pre_pos; // knoten *pre_pos; smartPointer sp_anfang; // knoten *anfang; //... if (sp_anfang == NULL) // Leere Liste sp_anfang = sp; if (sp_pre_pos != NULL) // Positionszeiger hat einen Vorgänger sp_pre_pos->setKnoten(sp->get()); else // neues Element steht am Anfang sp_anfang = sp; sp_pos = sp; // Positionszeiger zeigt nun auf das neue Element
Die Zuweisungen in den "IFs" können ja nicht funktionieren wenn der operator=(const smartPointer&) private ist.
-
- Bezeichner nicht mit _ anfangen! (die sind reserviert)
- kein using namespace std in Headerdateien!
- Warum machst Du die Knoten-Klasse so kompliziert?struct node { int data; node* next; };
...tut es doch auch.
- Der Konstrtuktor von smartPointer sollte
explizit
sein
- Wozu hat smartPointer einen virtuellen Destruktor ?!
- "operator bool() const" macht man nicht, siehe "safe bool idiom"
- Den Defaultparameter für den Konstruktor solltest Du in die Klassendefinition verlagernDas ganze Zeug mit dem smartPointer solltest Du Dir wahrscheinlich sparen und es eher so machen:
class list { node* first; node* last; public: list() : first(0), last(0) {} list(list const&); list& operator=(list const&); ~list(); ... }; list::~list() { while (first) { node* temp = first->next; delete first; first = temp; } }
u.s.w.