Doppelter operator ->(), aber nur einmal hingeschrieben


  • Administrator

    Grüsse zusammen,

    Kann mir einer erklären, wieso das geht? Oder liegt das an meinem Compiler, dass er nicht Standardkonform ist:

    #include <iostream>
    
    class Outer
    {
    private:
      class Inner
      {
      public:
        Inner* operator ->() { return this; };
    
        void test() { std::cout << "test" << std::endl; };
      };
    
    public:
      Inner operator ->()
      {
        return Inner();
      }
    };
    
    int main()
    {
      Outer outer;
      outer->test();
      // Wieso muss ich hier nur einmal den operator ->() hinschreiben?
    
      return 0;
    }
    

    Grüssli



  • Der Compiler übernimmt das für dich. Durch das Hinschreiben des einen Operators ist bereits gesichert, dass solange ein Objekt bzw. eine Referenz zurückgegeben wird der -> Operator dieses Objekts aufgerufen wird, bis ein Zeigertyp zurückkommt auf den dann der vordefinierte ->Operator angewendet werden kann.

    P.S.: Hat noch jemand Probleme mit dem Forum? Die Seite kann bei mir häufig nicht geladen werden.



  • Kritiker schrieb:

    P.S.: Hat noch jemand Probleme mit dem Forum? Die Seite kann bei mir häufig nicht geladen werden.

    Yep, bei mir genauso.



  • Ich werfe einfach noch mal eine Frage dazu (ich wollte auch mal einen Thread dazu aufmachen): Wieso funktioniert das eigentlich bei Iteratoren nicht?:

    std::vector<Foo*>::iterator v;
    v->foo();
    

  • Administrator

    Badestrand schrieb:

    Ich werfe einfach noch mal eine Frage dazu (ich wollte auch mal einen Thread dazu aufmachen): Wieso funktioniert das eigentlich bei Iteratoren nicht?:

    std::vector<Foo*>::iterator v;
    v->foo();
    

    Weil bereits ein Zeiger zurückkommt, nehme ich an. Der opterator ->() vom Iterator in diesem Fall, liefert wohl ein Foo**.

    @Kritiker,
    Danke für die Antwort. Das ist mal wieder ein geile Feature von C++ zum Ausnutzen 🙂

    Grüssli



  • Nehmen wir an, a sei vom Typ A, und foo ein Element des Typs A. Weiterhin habe A einen überladenen operator->. Dann passiert bei der Dereferenzierung über -> folgendes:

    a->foo /* (1) entspricht */
    
    decltype( A::operator-> ) tmp = a::operator->(); 
    tmp->foo /* (2a) wenn decltype( A::operator-> ) ein Zeigertyp ist, wissen wir was passiert: (*tmp).foo */
             /* (2b) wenn decltype( A::operator-> ) ein Objekttyp ist: GOTO (1) */
    

    Sprich, wenn das Ergebnis eines operator-> ein Typ ist, der selbst einen überladenen operator-> hat, wird dieser aufgerufen. Erst wenn das Ergebnis eines operator-> ein Zeigertyp ist, wird dereferenziert.

    Bei Iteratoren klappt das nicht, weil das Ergebnis eines vector<int*>::operator-> vom Typ int** ist. Und ein int** ist, einmal dereferenziert, ein int*. Da ein int* kein Objekttyp mit überladenem operator-> ist, greift die o.a. Regel nicht.


Anmelden zum Antworten