Überladen des Operator[] bei template



  • Guten Tag nette c-plusplus Foren Member.

    Zur Vorgeschichte:
    Ich hab nach (http://fatman98.fa.funpic.de/builder_array.php) von f98 immer die
    Dynamischen Arrays mit "DynamicArray<TYP>" benutzt.
    Fand es aber irgendwie Umständlich immer den DynamicArray einsatzbereit zu machen
    und Werte hinzuzufügen.

    DynamicArray<TYP> dArray;
    dArray.Length=1;
    dArray[dArray.Length-1]=WERT;
    

    Also habe ich eine Klasse geschrieben die diese per "Add" Funktion
    automatisch regelt. Als ich diese Klasse für String und int geschrieben
    und festgestellt hatte, das sich außer den TYP nicht verändert am Code,
    viel mir ein das es ja sowas nettes wie templates gibt.

    Nach ein bisschen Try&Error Verfahren (Ich liebe dieses Verfahren 😋) kam dann letzlich das heraus:

    // Klasse
    template <class T>
    class TDynArray
    {
    public:
        TDynArray(){this->Length=0;}
        ~TDynArray(){this->Length=0;}
    //---------------------------------------------------------------------------
        DynamicArray<T> Data;
    //---------------------------------------------------------------------------
        __property int Length = {read=get_length, write=set_length};
    //---------------------------------------------------------------------------
        void Add(T AddData){
            this->Data [this->Length]=AddData;
            this->Length++;
        }
    //---------------------------------------------------------------------------
    private:
        int Counter;
    //---------------------------------------------------------------------------
        bool is_inRage(int Index){
            return (Index<=this->Length&&Index>=0);
        }
    //---------------------------------------------------------------------------
        int  get_length(){
            return this->Counter;
        }
    //---------------------------------------------------------------------------
        void set_length(int l){
            this->Counter = l;
            this->Data.Length = l+1;
        }
    //---------------------------------------------------------------------------
    };
    

    Meine Test mit der TDynArray Klasse:

    TDynArray<AnsiString> * Test=new TDynArray<AnsiString>();
        Test->Add("Ich Teste");
        Test->Add("den Dyn.");
        Test->Add("Array");
        for(int i=0;i<Test->Length;i++)
        Memo1->Lines->Add(Test->Data[i]);
    

    So das Funktioniert auch Prächtig.

    Problem:
    So, da ich finde das der Aufruf "Test->Data[i]" länger ist wie "Test[i]"
    würde ich gerne den Operator[] überladen.
    Dabei hab ich mir gedacht das müsst über diese Struktur funktionieren:

    T operator[](int index){
            if(this->is_inRage(index))return this->Data[index];
            return NULL;
        }
    

    Der Kompiler meckert auch in der Klasse nicht darüber.

    Allerdings wenn ich meine Test Funtkion mit

    AnsiString wtf=Test[0];
    

    erweitere meckert der Kompiler mit:

    [BCC32 Fehler] Unit2.cpp(512): E2285 Keine Übereinstimmung für 'AnsiString::AnsiString(const AnsiString&)' gefunden

    Wenn das beantwortet wurde, wäre natürlich die Frage:
    Wie müsste die Struktur aussehen wenn man direkt über [] setzen kann.

    Test[0]="Test";
    

    Nur noch mal als Hinweis: Ich habe noch nicht wirklich mit Operatoren
    Überladungen gearbeitet. Zwar hab ich schon ein Paar Klassen mit
    Überladungen getestet, aber keine war im Bezug auf ein template.

    Danke im Voraus für die Konstruktive Kritik und Code Erweiterungen ;>

    mfg Paule



  • Hallo

    Da Test ja ein Pointer auf eine Instanz ist, must du den Pointer erstmal dereferenzieren.

    AnsiString wtf=(*Test)[0];
    

    Damit du mit dem []-Op auch Werte verändern kannst must du eine Referenz übergeben

    T& operator[](int index){
            if(this->is_inRage(index))return this->Data[index];
            return NULL;
        }
    

    Daraus ergibt sich aber das Problem der const-Correctness, so das du besser zwei Operatoren anbieten solltest

    const T& operator[](int index) const{
            if(this->is_inRage(index))return this->Data[index];
            return NULL;
        }
    T& operator[](int index){
            if(this->is_inRage(index))return this->Data[index];
            return NULL;
        }
    

    3. Du solltest deine Klasse nur als Test betrachten. Und für den reallen einsatz lieber std::vector nehmen, das ist nämlich genau das was du machen willst, nur schon fertig, umfangreicher und effizienter 😉
    Siehe dazu auch den Magazin-Artikel hier im Forum zu den STL-Containern.

    4. Der Sinn bei solchen dynamischen Containern ist das die Container selber auf dem Stack angelegt werden, die Elemente aber auch dem Heap.
    Deshalb sollte (auch bei std::vector) das eher so aussehen :

    DynArray Test();
    Test.Add("Neu");
    

    Den Container selber auf den Heap (Pointer, new...) sollte man nur machen wenn es wirklich notwendig ist, und das sollte es in den wenigsten Fällen.

    bis bald
    akari



  • Hallo zurück.

    Huch das ging ja schnell.

    Danke akari mit dem dereferenzieren klappt das wunderbar,
    ist jetzt mein neues Lieblingswort 😃 .

    Danke für die Code-Verbesserungen und für den Hinweis
    mit dem STL, ich werd es mir mal anschauen.

    mfg
    Paule


Anmelden zum Antworten