(C++) Index-Operator überladen in Klassentemplate
Jens Holzkämper
- programmiertechnik
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
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[].
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
Tach,
Nimm am Besten
size_t
anstelle vonunsigned 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