Jens Holzkämper: (C++) Index-Operator überladen in Klassentemplate

Tach,

für meine Hausaufgabe soll ich quasi Teile der Vektor-Klasse als Klassentemplate in C++ neu implementieren, Probleme macht mir momentan das Überladen des Index-Operators []. Der (gekürzte) Quelltext sieht wie folgt aus:

  
template<typename T> class Vector  
{  
private:  
 unsigned int length;  
 T* daten;  
  
 unsigned int getLength(){return this->length;}  
 T* getDaten(){return this->daten;}  
 void setDaten(T* daten){this->daten=daten;}  
  
public:  
 Vector(void){  
  this->setLength(0);  
  this->setCapacity(100);  
  daten = new T[100];  
 }  
 ~Vector(void){  
  delete daten;  
 }  
  
 void push_back(T element);  
 T& operator[](unsigned int position){return this->getDaten()[position];}//funktioniert nicht  
 T& out(unsigned int position){return this->getDaten()[position];}//funktioniert  
 unsigned int size(){return getLength();}  
};  
  
template <typename T> void Vector<typename T>::push_back(T element){  
 daten=this->getDaten();  
 daten[this->getLength()]=element;  
 this->setDaten(daten);  
}  
  
void main(){  
 Vector<int>* erwin = new Vector<int>;  
 erwin->push_back(12345);  
 erwin->push_back(678);  
 int a = erwin->out(1);  
 int b = erwin[1];  
}  

Beim Kompilieren (Visual Studio .Net 2003) wird die vorletzte Zeile (int b = erwin[1];) angekreidet und ich erhalte die Fehlermeldung "error C2440: 'initializing' : cannot convert from 'Vector<T>' to 'int' with [ T=int ]". Da die testweise eingebaute Methode out funktioniert, vermute ich, dass meine Operator-Definition komplett übergangen wird. Leider habe ich im Moment nicht den blassesten Schimmer wieso.

mfg
Woodfighter

  1. Vector<int>* erwin = new Vector<int>;
    int a = erwin->out(1);
    int b = erwin[1];
    }

    Beim Kompilieren (Visual Studio .Net 2003) wird die vorletzte Zeile (int b = erwin[1];) angekreidet

    erwin ist kein Objekt, sondern ein Zeiger auf ein Objekt. Deshalb kannst Du zwar mit erwin->out() und (*erwin)[] arbeiten, aber nicht mit erwin.out() und erwin[].

  2. Moin!

    Der (gekürzte) Quelltext sieht wie folgt aus:

    template<typename T> class Vector
    {
    private:
    unsigned int length;

      
    Nimm am Besten `size_t`{:.language-c++} anstelle von `unsigned int`{:.language-c++}, da size\_t genau so dimensioniert ist, wie deine Plattform maximal an Arbeitsspeicher verwalten kann.  
      
    
    >  ~~~c++
    
    T* daten;  
    
    >   
    >  unsigned int getLength(){return this->length;}  
    >  T* getDaten(){return this->daten;}  
    >  void setDaten(T* daten){this->daten=daten;}  
    >   
    > public:  
    >  Vector(void){
    
    

    In C++ brauchst diese „C-Schreibweise“ nicht mehr, stattdessen schreibt man:

    Vektor() {, wobei der Code für setLength() und setCapacity noch fehlt:

    this->setLength(0);

    this->setCapacity(100);
      daten = new T[100];
    }
    ~Vector(void){
      delete daten;
    }

      
    Du legst daten doch als Array an, von daher musst du den Operator `delete`{:.language-c++} in der Arrayschreibweise benutzen:  
      
    ~~~c++
    ~Vektor() {  
        delete[] daten;  
    }
    

    void push_back(T element);

    T& operator[](unsigned int position){return this->getDaten()[position];} //funktioniert nicht
    T& out(unsigned int position){return this->getDaten()[position];} //funktioniert
    unsigned int size(){return getLength();}
    };

      
    Beim ersten Kompilieren mit dem GCC fiel mir auf, dass in der Zeile hier drüber die Klassendefinition ja zu Ende ist, der GCC stößt sich daher an folgendem Code:  
      
    
    > ~~~c++
    
    template <typename T> void Vector<typename T>::push_back(T element){  
    
    >  daten=this->getDaten();  
    >  daten[this->getLength()]=element;  
    >  this->setDaten(daten);  
    > }
    
    

    Wenn ich diese Methode folgendermaßen _in die Klasse_ integriere, gibt es soweit keine Fehler mehr, allerdings verstehe ich nicht, wieso du daten sich selbst zuweist:

    void push_back(T element){  
        daten=this->getDaten();  
        daten[this->getLength()]=element;  
        this->setDaten(daten);  
    }
    

    Dafür allerdings im Folgenden:

    void main(){

    Vector<int>* erwin = new Vector<int>;
    erwin->push_back(12345);
    erwin->push_back(678);
    int a = erwin->out(1);
    int b = erwin[1];
    }

      
     • error: `main' must return `int'  
     • error: cannot convert `Vector<int>' to `int' in initialization, bezogen auf  
       `int b = erwin[1];`{:.language-c++}  
       was auch logisch ist, schließlich ist erwin \_ein Pointer, kein Objekt\_.  
      
    Basierend auf deinem eigentlichen Problem gibt es zwei Möglichkeiten:  
      
    1\. An erwins Element 1 kommst du mit dem []-Operator wie folgt:  
       `int b = erwin->operator[](1);`{:.language-c++}  
      
    2\. Erzeuge erwin „statisch“, nicht dynamisch (auch wenn man damit auf die „coolen Pointerpfeile“ verzichten muss):  
      
    `Vector<int> erwin;`{:.language-c++}  
      
    Schönen Sonntag,  
    Robert
    
    1. Tach,

      Nimm am Besten size_t anstelle von unsigned int, da size_t genau so dimensioniert ist, wie deine Plattform maximal an Arbeitsspeicher verwalten kann.

      guter Hinweis, hatte nur das int aus der Aufgabenstellung in ein unsigned gewandelt um mich um die Überprüfung auf positive Werte zu drücken.

      In C++ brauchst diese „C-Schreibweise“ nicht mehr, stattdessen schreibt man:

      Hätte ich getan, der Code war von der IDE eingefügt.

      Vektor() {, wobei der Code für setLength() und setCapacity noch fehlt:

      Schon klar, hatte ich zum Kürzen rausgeschmissen.

      Du legst daten doch als Array an, von daher musst du den Operator delete in der Arrayschreibweise benutzen:

      ~Vektor() {

      delete[] daten;
      }

        
      Danke, da wäre ich sicher noch drüber gestolpert.  
        
      
      > Beim ersten Kompilieren mit dem GCC fiel mir auf, dass in der Zeile hier drüber die Klassendefinition ja zu Ende ist, der GCC stößt sich daher an folgendem Code:  
        
      Dann werfe ich das da auch mal rein, finde ich übrigens recht unschön, dass es hier scheinbar nicht mehr möglich ist Definitionen und Deklarationen klar zu trennen.  
        
      
      > Wenn ich diese Methode folgendermaßen \_in die Klasse\_ integriere, gibt es soweit keine Fehler mehr, allerdings verstehe ich nicht, wieso du daten sich selbst zuweist:  
        
      Gute Frage, nächste Frage.  
        
      
      >  • error: `main' must return `int'  
        
      Ist klar, fiel hier Q&D zum Opfer.  
        
      
      >  • error: cannot convert `Vector<int>' to `int' in initialization, bezogen auf  
      >    `int b = erwin[1];`{:.language-c++}  
      >    was auch logisch ist, schließlich ist erwin \_ein Pointer, kein Objekt\_.  
        
      \*Kopf auf Tischplatte\*  
        
      mfg  
      Woodfighter