operator []() will nicht?!



  • Hi,

    so direkt noch eine andere Frage hinterher. 😃

    Ich war etwas verwirrt, als mir folgendes aufgefallen ist (arbeite mit C++ Builder 2007):

    Ich besorge mir z.B. von einer TComponentList (aber das passiert auch bei anderen Objekten) ein Item:

    TMyComp* PComp;
    TComponentList *MyCompList = new TComponentList();
    ...
    PComp = MyCompList[index];
    

    Das führt zu dem Fehler: [BCC32 Fehler] E2031 Typumwandlung von 'TComponentList' nach 'TMyComp *' nicht zulässig.

    Mal vom anständigen casten abgesehen, man beachte 'TComponentList' und 'TMyComp ****'. Schließlich gibt der []-Operator ein TComponent zurück. 😕

    So klappt es:

    TMyComp* PComp;
    TComponentList *MyCompList = new TComponentList();
    ...
    PComp = MyCompList->operator[](index);
    

    Äh,ja, Ideen?



  • Ja, nimm mal das ; vor [ weg 🙄



  • Hi,

    😃 Das ist kein kopierter Code, sondern denn habe ich grade exemplarisch hier rein geschrieben.
    Hab mich natürlich nur vertippt. 😉

    So: korrigiert.



  • Hallo

    Wo ist dein Problem?
    Wenn du statt dem []-Operator die Eigenschaft Items benutzt und richtig castest (wie du es doch selber noch kommentierst) ist es doch ganz in Ordnung?

    TLabel* PComp;
    TComponentList *MyCompList = new TComponentList();
    ...
    PComp = static_cast<TLabel*>(MyCompList->Items[index]);
    

    Wenn du nicht casten und auch den []-Op benutzen willst dann benutzt lieber std::vector<TMyComp>* als Container, der ist wesentlich eleganter, auf dem Stack anlegbar und außerdem aus dem C++ Standard.

    bis bald
    akari



  • Hi akari,

    es ist ja kein Problem, weil ich es so und so ähnlich auch mache.
    Es ist eher eine Verständnisfrage.

    Ich verstehe nicht, warum es nicht einfach mit dem []-Operator klappt.
    In der Hilfe steht ja auch:

    Anmerkung: In Delphi ist Items die Standardeigenschaft von TComponentList. Der Name der Eigenschaft muss also im Quelltext nicht angegeben werden. Die beiden folgenden Zeilen sind damit gleichwertig:

    ComponentList1->Items[i] := Screen.CustomForms[i];
    ComponentList1[i] := Screen.CustomForms[i];

    Anmerkung: In C++ kann auf Items mit dem Operator [] zugegriffen werden, um einen ähnlichen Effekt wie mit der Standardeigenschaft in Delphi zu erreichen.

    Mmhh, wenn ich mir jetzt die letzte Anmerkung nochmal durchlese komme ich in geringe Zweifel... Das heißt doch eigentlich, dass es mit ComponentList1[i] funktionieren müsste oder bedeutet das es geht nur in Delphi und für C++ müsste man ComponentList1->Items[i] benutzen?!

    Ach, heute ist nen scheiß Tag. Ich glaube ich will gar nicht mehr darüber nachdenken 😞

    Vielen Dank trotzdem!



  • Hallo

    In C++ must du eben nur noch zusätzlich den Pointer dereferenzieren, um den []-Operator anwenden zu können

    PComp = static_cast<TLabel*>((*MyCompList)[index]);
    

    bis bald
    akari



  • __yoshi schrieb:

    Mmhh, wenn ich mir jetzt die letzte Anmerkung nochmal durchlese komme ich in geringe Zweifel... Das heißt doch eigentlich, dass es mit ComponentList1[i] funktionieren müsste oder bedeutet das es geht nur in Delphi und für C++ müsste man ComponentList1->Items[i] benutzen?!

    Nein, das heißt tatsächlich, daß das eigentlich nur in Delphi geht, in C++Builder aber explizit die Untereigenschaft angegeben werden muß. Allerdings hat sich das in C++Builder 6 geändert:

    C++Builder 6-Dokumentation/Neuerungen schrieb:

    Subscript-Operatoren

    Ein Object Pascal-Merkmal, das Benutzern von C++Builder bisher vorenthalten war, ist die sogenannte Standardeigenschaft (eine indizierte Eigenschaft, die über einen Subscript-Operator angesprochen wird). VCL- und CLX-Klassen, die in Object Pascal eine Standardeigenschaft haben, unterstützen nun in C++ einen Subscript-Operator, der demselben Zweck dient. Allerdings müssen Sie den Objektzeiger dereferenzieren, bevor Sie ihn verwenden. Anstelle von

    Strings1->Strings[i]

    können Sie nun schreiben:

    (*Strings1)[i]

    Wenn du einmal die Deklaration von TComponentList ansiehst, siehst du das:

    class DELPHICLASS TComponentList;
    class PASCALIMPLEMENTATION TComponentList : public TObjectList 
    {
    	typedef TObjectList inherited;
    
    public:
    	Classes::TComponent* operator[](int Index) { return Items[Index]; }
            ...
    

    Um viel mehr handelt es sich dabei nicht. Allerdings hast du in deinem Beispiel natürlich einen Zeiger auf TComponentList, und wenn du den indizierst, resultiert das notwendigerweise in undefiniertem Verhalten. Du mußt den Zeiger dereferenzieren, wie akari schreibt.



  • Hi,

    vielen Dank für eure ausführliche Erklärung!

    Ich weiß jetzt, warum mir das so unbekannt und merkwürdig vorkam.
    Hab's begriffen ^^


Anmelden zum Antworten