Problem mit operator[]



  • Hi,

    ich habe heute schon einmal gepostet. Falls das Problem, was ich hier anspreche eigentlich in den selben Thread gehört: Bitte verschieben. Und sorry für die Arbeit.

    Ich habe eine Klasse deklariert, bei der ich den Befehl operator für ein Element verwendet habe:

    class A
    {
    ...
    };
    
    class B
    {
    ...
    private:
    A* GetNr(Index);
    ...
    public:
    A* operator[](int Index) {return GetNr(Index);};
    ...
    };
    

    Ich würde in der Klasse B gerne Zeiger auf die Klasse A anlegen/löschen/verwalten. Wenn ich nun "B->" eingebe, wollte ich eigentlich auf die Elemente von B zugreifen und wenn ich "B[Nummer]->" eingebe auf die Elemente von A. Versuche ich nun aber "pB[Nummer]->Element" (wobei pB als ein Zeiger auf B deklariert ist) so erhalte ich folgende Meldung:
    Zeiger auf Struktur auf linker Seite von -> oder von ->* erforderlich*

    Hat da irgendjemand eine Idee? Geht das überhaupt so, wie ich mir das vorstelle?



  • Du musst pB erst dereferenzieren, bevor du mit dem op[] drauf zugreifst:

    (*pB)[Index]->IrgendeinMethodeVonA();
    


  • Super, hat funktioniert. Ich verstehe aber ehrlich gesagt nicht, wieso?
    Wenn ich einen Zeiger auf die Klasse A deklariere, kann ich doch mit "A->" auf die einzelnen Elemente zugreifen. Wenn ich nun "pB[Nummer]->" eingebe, sollte ich doch einen Zeiger auf A als Ergebnis erhalten und demnach mit "->" auch hier auf die einzlnen Elemente zugreifen können. "->" wird doch benutzt um bei einem Zeiger auf die Elemente zuzugreifen, oder?



  • Wenn du ein B oder eine Referenz auf ein B (aber keinen Zeiger) hast, geht b[n]->blub() ja auch. pB ist ein Zeiger, und deshalb musst du zweimal dereferenzieren - einmal pB selbst, einmal den von [] zurückgegebenen Wert - und das tut pB[n]-> nicht. Umständlich (aber direkter) könntest du schreiben pB->operator[](n)->, oder eben (*pB)[n]->.



  • Cool, danke. Das ist jetzt *denke ich* angekommen.

    Ich hätte dann aber noch eine Frage:
    Meine Problem ist nun, daß ich mittlerweile folgende Situation habe:

    class A
    {
    public:
    void AFunc();
    };
    
    class B
    {
    private:
    A* GetNr(Index);
    public:
    A* operator[](int Index) {return GetNr(Index);};
    };
    
    class C
    {
    public:
    B* pB;
    };
    
    class D
    {
    private:
    C* GetNr(Index);
    public:
    C* operator[](int Index) {return GetNr(Index);};
    };
    

    Ich habe das ganze also eigentlich um eine Ebene mehr verschachtelt. Wenn ich nun auf A zugreifen will, habe ich folgendes versucht:

    D[0]->pB[0]->AFunc();
    

    Wie ich erklärt bekommen habe , kann es so nicht funktionieren. Also habe ich das folgende gemacht:

    (*D)[0]->(*pB)[0]->AFunc();
    

    Aber auch das funktioniert nicht. Es funktioniert, wenn ich es so mache:

    D->operator[](0)->pB->operator[](0)->AFunc();
    

    Aber das ist natürlich nicht besonders schön. Ich bin gerade dabei eine Komponente zu entwickeln, die nachträgliche mehrere Entwickler verwenden werden. Zwar nur privat, aber es wäre trotzdem schön, wenn man das eleganter machen könnte.
    Sollte ich die Deklaration vielleicht komplett ändern? Ich wäre wirklich für alle Vorschläge offen...

    Ich hätte halt gerne, das es auch eine "schöne" Komponente wird. Also wäre es schon elegant, wenn man einfach über folgendes auf AFunc() zugreifen kann:

    D[0]->pB[0]->AFunc();
    


  • BorlandUser schrieb:

    (*D)[0]->(*pB)[0]->AFunc();
    

    Du musst das * vor den ganzen Ausdruck stellen, den du dereferenzieren willst:

    (*(*D)[0]->pB)[0]->AFunc();
    

    Erstmal solltest du gucken, ob du vielleicht Zeiger verwendest, wo du keine brauchst (irgendwie verleitet dein Name zu der Annahme, sorry 😉 ). Kannst du an einer Stelle vielleicht ein Objekt direkt verwenden, statt eines Zeigers darauf? Können bestimmte Funktionen vielleicht Referenzen zurückgeben, weil der darunter liegende Zeiger logisch nie 0 sein kann?
    Wenn das alles nicht hilft, würde ich einfach nicht operator[] überladen, sondern eine normale Elementfunktion nehmen. Normalerweise soll [] ja Tipparbeit sparen, aber wenn es das nicht tut, kann man auch eine normale Funktion verwenden:

    D->get(0)->pB->get(0)->AFunc();
    


  • Für das mit dem Namen mußt Du nicht entschuldigen. Stimmt wahrscheinlich sogar. 🙄
    Das mit dem direkt einbinden ist so eine Sache. Habe ich schon im Ansatz probiert, war aber nicht wirklich erfolgreich. Ich werde es noch einmal versuchen. Wenn es nicht klappt, kann ich das, was ich realisieren will ja noch einmal im Detail beschreiben. Das mit der Funktion ist eigentlich eine ziemlich gute Idee.

    Beides werde ich einfach mal probieren. Denn auch als Borland-Benutzer ist man für neue Dinge offen. 😃



  • Keine Sorge, ich bin auch Ex-Delphier 😉 Aber im Gegensatz zu dem, was man mir damals immer in Delphi-Newsgroups weismachen wollte, braucht man in C++ wesentlich seltener Pointer als in Delphi, und wenn, dann kann man die meiste Pointer-bezogene Drecksarbeit noch an std::auto_ptr und andere Wrapper abwälzen. Ich habe ne Weile gebraucht, bis ich mich daran gewöhnt hatte, aber seitdem habe ich auch keine Pointerprobleme mehr 🙂


Anmelden zum Antworten