CopiedPointer...
-
Ich habe mir eine Autopointerklasse geschrieben udn sie gibt mir beim Kompilieren eines Beispiels einen Fehler... Warum?
template<class T> class CopiedPointer_ { protected: T* pointer_; public: // Standartd Konstruktor CopiedPointer_(void) : pointer_(0) { } CopiedPointer_(T* pointer) : pointer_(pointer) { } // Copy-Konstruktor CopiedPointer_(const CopiedPointer_<T>& copied_pointer) : pointer_(copied_pointer.is_zero() ? 0 : new T(*copied_pointer.pointer_)) { } // Destruktor ~CopiedPointer_(void) { delete pointer_; } // Assignment Operator CopiedPointer_<T>& operator =(T* pointer) { // alten Zeiger löschen delete pointer; // neuen zuweisen pointer_ = pointer; return(*this); } // Assignment Operator CopiedPointer_<T>& operator =(const CopiedPointer_<T>& copied_pointer) { // prüfen, das nicht dasselbe Objekt übergeben wurde if(pointer_ != copied_pointer.pointer_) { delete pointer_; // wenn die Refernez 0 ist, wird pointer auch auf 0 gesetzt pointer_ = copied_pointer.is_zero() ? 0 : new T(copied_pointer.pointer_); } return(*this); } // Operator gibt Addresse des Zeigers zurück T& operator *(void) const { return(*pointer_); } // prüft, ob Zeiger ins leere Zeigt und somit leer ist bool is_zero(void) const { return(pointer_ == 0); } void zero(void) { delete pointer_; pointer_ = 0; } // Vergleichsoperator friend bool operator==(const CopiedPointer_<T>& copied_pointer_a, const CopiedPointer_<T>& copied_pointer_b) { return(copied_pointer_a.pointer_ == copied_pointer_b.pointer_); } // Vergleichsoperator friend bool operator!=(const CopiedPointer_<T>& copied_pointer_a, const CopiedPointer_<T>& copied_pointer_b) { return(copied_pointer_a != copied_pointer_b); } }; template<class T> class CopiedPointer : public CopiedPointer_<T> { public: // Konstruktor CopiedPointer(void) : CopiedPointer_<T>() { } // Copy-Konstruktor CopiedPointer(const CopiedPointer<T>& copied_pointer) : CopiedPointer_<T>(copied_pointer) { } // Assignment Operator CopiedPointer<T>& operator =(T* pointer) { CopiedPointer_<T>::operator =(pointer); return(*this); } // Assignment Operator CopiedPointer<T>& operator =(const CopiedPointer<T>& copied_pointer) { CopiedPointer_<T>::operator =(copied_pointer); return(*this); } T* operator->(void) const { return(pointer_); } };#include "CopiedPointer.hpp" #include <iostream> using namespace std; struct test { int a_, b_; test(void) : a_(0), b_(0) { } test(int a, int b) : a_(a), b_(b) { } }; int main(void) { CopiedPointer<test> ptr = new test(1, 5); cin.get(); return 0; }Fehlermeldung: error C2440: 'Initialisierung': 'test *' kann nicht in 'CopiedPointer<T>' konvertiert werden 1> with 1> [ 1> T=test 1> ] 1> Quelltyp konnte von keinem Konstruktor angenommen werden, oder die Überladungsauflösung des Konstruktors ist mehrdeutig
-
Eine Konstruktion mit Zuweisung ist äquivalent mit einer direkten Konstruktion. Der Compiler liest in dieser Zeile also:
CopiedPointer<test> ptr( new test(1, 5) );Versuch mal folgendes, das müsste mit der derzeitigen Klasse funktionieren:
CopiedPointer<test> ptr; ptr = new test(1, 5);Das aber nur als Erklärung, eleganter ist sicherlich die Initialisierung wie sie jetzt ist. Damit die funktioniert, musst Du Deiner Klasse noch einen Konstruktor spendieren, der als Parameter ein T* entgegennimmt.
-
Ok, ich habe den Konstruktor in der CopiedPointer Klasse tatsächlich vergessen, aber vielen Dank!
-
Hier sind mehrere Sachen unglücklich oder gefährlich. Was allerdings auffällt, ist der fehlende Sinn der Vergleichsoperatoren. Beim jetzigen Design dürfen zwei deiner Zeiger sowieso nur gleich sein, wenn du den Zeiger mit sich selbst vergleichst (es sei denn beide sind leer), andernfalls hast du es später mit einem doppelten delete zu tun.
-
- wieso trennst du das in 2 Klassen auf?
- wenn ein Template "seinen eigenen Namen verwendet", dann brauchst du die Template Parameter nicht zu wiederholen:
template<class T> struct a { // a(a<T> const& other); // kürzer: a(a const& other); };- der ctor mit "T*" als Argument sollte "explicit" sein, sonst kannst du da lustige Überraschungen erleben
- der "operator =" mit "T*" ist ebenfalls gefährlich (mach ne ".reset()" Funktion stattdessen)
- der operator != ist rekursiv (ruft sich selbst auf)
- der Name "zero" ist IMHO unglücklich gewählt
...
-
Warum ist der operator= mit T* gefärhlich?
-
und warum ist der operator!= rekuriv?
-
g--. schrieb:
und warum ist der operator!= rekuriv?
Weil der operator!= die beiden Objekte auf Ungleichheit prüft, was den operator!= aufruft, welcher die beiden Objekte auf Ungleichheit prüft, was den operator!= aufruft, welcher die beiden Objekte auf Ungleichheit prüft, was den operator!= aufruft, welcher die beiden Objekte auf Ungleichheit prüft, was den operator!= aufruft, ....
EDIT:
Meintest Du evtl.:return !(copied_pointer_a == copied_pointer_b);
-
Kann ich auch hier:
CopiedPointer<T>& operator =(T* pointer)das <T> weglassen?
-
Ich habe koch eine kleine Frage:
Wie kann ich den Vergleichsoperatoren überladen, sodass sie den Wert des Zeigers vergleichen? udn nicht die Adresse?
Problem ist ja dabei, das bei dem template der == und != Operator definiert sein muss? Oder gibt es irgendwelche umwege, wie ich zwei meiner CopiedPointer Objekte bezüglich der Werte des Zeigers vergleuchen kann?
mfg
-
Den "operator = (T*)" halte ich für gefährlich weil es dadurch eine Funktion gibt, die einen "CopiedPointer" als Argument nehmen kann oder auch einen "rohen T*", deren Semantik sich aber in beiden Fällen unterscheidet.
Wenn ein "CopiedPointer" übergeben wird wird dieser kopiert, wenn allerdings ein "T*" übergeben wird gibt man damit die Ownership ab.2 Operationen gleichen namens die was grundlegend unterschiedliches machen... nicht gut.
Und ja, ich denke du kannst auch dort das "<T>" weglassen, probier es doch einfach aus.
BTW: noch ein Fehler in deinem Code, nämlich genau im "operator =(T*)":CopiedPointer_<T>& operator =(T* pointer) { // alten Zeiger löschen delete pointer; // ba-da-boom, falscher Zeiger gelöscht, da fehlt ein "_" // neuen zuweisen pointer_ = pointer; return(*this); }Und: du kannst Objekte vergleichen wenn ein geeigneter "operator ==" definiert ist. Wenn nicht, dann nicht. Und auch nicht in deinem Template. Frag dich lieber ob du das überhaupt brauchst.