-- Postifix-Operator



  • Hi 🙂

    Ich hab mal wieder eine Frage zu einem Programm. Leider verstehe ich nicht, was da abläuft.

    Und zwar geht es um das Überladen des -- Postfix-Operators (also Methode in Zeile 26 von Datei automat.cpp.

    Hier mal das Hauptprogramm main.cpp:

    #include <iostream>
    #include "automat.h"
    using namespace std;
    
    int main(void) {
    
      Automat data01;
    
      ++data01; 
      cout << data01.get_zugriffe() << endl;
    
      data01++; 
      cout << data01.get_zugriffe() << endl; // zugriffe = 2
    
      --data01; 
      cout << data01.get_zugriffe() << endl; // zugriffe = 1
    
      data01--; 
      cout << data01.get_zugriffe() << endl; // zugriffe = 0
    
      return 0;
    }
    

    automat.h:

    #ifndef _AUTOMAT_H_
    #define _AUTOMAT_H_
    #include "automat.h"
    
    class Automat {
      private:
        static int zugriffe;
    
      public:
        // Präfix
        Automat& operator++();   // ++objekt
        Automat& operator--();   // --objekt
    
        // Postfix
        Automat operator++(int); // objekt++
        Automat operator--(int); // objekt--
    
        int get_zugriffe() const;
    };
    
    #endif
    

    Und automat.cpp:

    #include "automat.h"
    
    int Automat::zugriffe = 0;
    
    // Präfix
    
    Automat& Automat::operator++() {
      zugriffe++;
      return *this;
    }
    
    Automat& Automat::operator--() {
      if(zugriffe > 0)
         zugriffe--;
      return *this;
    }
    
    // Postfix
    
    Automat Automat::operator++(int) {
      Automat temp(*this);
      zugriffe++;
      return temp;
    }
    
    Automat Automat::operator--(int) { // <<<<<<<< -- Postfix
      Automat temp(*this);
      if(zugriffe > 0)
         zugriffe--;
      return temp;
    }
    
    int Automat::get_zugriffe() const {
      return zugriffe;
    }
    

    Hier nochmals diese spezielle Methode, die ich nicht verstehe:

    Automat Automat::operator--(int) { // <<<<<<<< -- Postfix
      Automat temp(*this);
      if(zugriffe > 0)
         zugriffe--;
      return temp;
    }
    

    Was passiert hier eigentlich? Zuerst wird scheinbar in temp eine Kopie vom eigenen Objekt angelegt. Dann ändert sich zugriff vom eigenen Objekt. Und dann wird die Kopie zurückgegeben. Das bedeutet doch, dass ich dann 2 voneinander unabhängige Objekte habe, oder?



  • tröröö schrieb:

    Was passiert hier eigentlich? Zuerst wird scheinbar in temp eine Kopie vom eigenen Objekt angelegt. Dann ändert sich zugriff vom eigenen Objekt. Und dann wird die Kopie zurückgegeben. Das bedeutet doch, dass ich dann 2 voneinander unabhängige Objekte habe, oder?

    Ja.

    Postfix bedeutet: Führe die Operation aus und gib den Wert zurück, den du vor der Operation hattest.
    Präfix bedeutet: Führe die Operation aus und gib deinen neuen Wert zurück (nach der Operation).

    Die einfachste Art, diese Semantik zu implementieren ist mit dem Hilfsobjekt. Jemand, der Postfix benutzt, weiss, dass das unter Umständen langsam ist. Präfix ist i.A. schneller.



  • Ja, das stimmt. Du implementierst übrigens beide Postfix-Operatoren auf die gleiche Art und Weise.

    Das Ding ist:
    Wenn eine ++ (oder analog dazu --) Anweisung für sich alleine steht, dann juckt das niemanden, die verhalten sich vollkommen gleich. (Bzw. sollten es!)
    Erst in Kombination mit anderen Answeisungen(lesen doer schreiben) wird das interessant:

    int i = 0;
    cout << i << endl; // 0
    cout << i++ << endl;  // 0
    cout << i << endl; // 1
    cout << ++i << endl; // 2
    cout << i << endl; // 2
    

    Und so wie du es implementiert hast ist der gewöhnliche Weg.
    Temporäre Kopie vom aktuellen zustand erzeugen, das Original (this) verändern und die Kopie zurückgeben.



  • Wie kann ich mir denn bei diesen Automaten-Beispiel im Hauptprogramm anschauen, ob das mit den Präfix- und Postifix-Operationen auch tatsächlich so funktioniert, wie ich das haben möchte?

    Aktuell mache ich im Hauptprogramm zuerst immer nur eine Addition oder Subtraktion und erst danach frage ich den Wert ab. Aber dadurch, dass Änderung und Ausgabe voneinander getrennt sind, sehe ich nicht, dass diese Präfix-/Postifix-Überladung wirklich so funktioniert wie eine normale Präfix-/Postfix-Operation.

    Irgendwie kommt mir dieses Programm, so wie es jetzt ist, ziemlich sinnlos vor.



  • ist es auch, du veränderst ja nichts am Objekt an sich, sondern durch die statische Variable an allen Objekten



  • Kann man das Programm irgendwie so umschreiben, damit das alles sinnvoller und klarer wird? 🙂



  • Die Variable nicht-statisch machen?



  • Ja, kann man sicher machen, aber das ändert am Hauptprogramm nichts. Und ich finde eigentlich das Hauptprogramm nicht gut. Es zeigt nicht, wodurch sich Präfix- von Postfix-Operatoren unterscheiden, weil Wertänderungen und Ausgaben im Hauptprogramm voneinander getrennt sind. Beim Progrämmchen vom Skym0sh0 sind sie nicht voneinander getrennt. Ich suche so etwas ähnliches, wo die Operatoren jedoch überladen wurden. Also so wie bei dem Automaten-Beispiel.



  • So?

    Automat data01;
    
      cout << (++data01).get_zugriffe() << endl;
      cout << data01++.get_zugriffe() << endl; // zugriffe = 2
      cout << (--data01).get_zugriffe() << endl; // zugriffe = 1
      cout << data01--.get_zugriffe() << endl; // zugriffe = 0
    


  • Na, ich glaube, das bringts auch nicht. Das sind je Zeile auch immer nur 2 voneinander getrennte Aktionen. Das kann meiner Meinung nach auch nicht den Unterschied zwischen Präfix- und Postfix-Operationen aufzeigen.



  • Hä?
    Was hast du denn überhaupt vor??

    Den Unterschied zwischen Prä- und Postinkrement (-dekrement) kann man super easy an einem Minimalbeispiel, wie ich es oben gepostet hab, zeigen.

    Wie das implementiert wird oder warum Präinkrement schneller ist, das hast du schon in deinem Code gezeigt.

    Wodrauf willst du also hinaus?



  • Ok, ich tu mir etwas schwer, das mit Worten zu beschreiben. Ich versuchs mal anhand eines Programms:

    #include <iostream>
    #include "automat.h"
    using namespace std;
    
    int main(void) {
    
      int i = 0;
      cout << i << endl; // 0
      cout << i++ << endl;  // 0
      cout << i << endl; // 1
      cout << ++i << endl; // 2
      cout << i << endl; // 2
    
      cout << "----------------------" << endl;
    
      Automat data01;
      cout << data01.get_zugriffe() << endl; // 0
      cout << (data01++).get_zugriffe() << endl; // hier kommt 1 statt 0!!!!
      cout << data01.get_zugriffe() << endl; // 1
      cout << (++data01).get_zugriffe() << endl; // 2
      cout << data01.get_zugriffe() << endl; // 2
    
      return 0;
    }
    

    In der Zeile 18 hätte ich eigentlich gerne die gleiche Ausgabe wie in Zeile 9.



  • Siehe:

    Bashar schrieb:

    Die Variable nicht-statisch machen?



  • Tatsächlich. Jetzt funktionierts. Seltsam 😕



  • tröröö schrieb:

    Tatsächlich. Jetzt funktionierts. Seltsam 😕

    Nein, wieso?

    Statische Variablen (Klassenvariablen) sind nicht an Objekte gebunden, sondern gelten für alle Objekte (Instanzen) einer Klasse. Ob du da jetzt was kopiert, gemoved oder sonstwas ahst, hat keine Auswirkungen.



  • OK. Dann schick ich dem Buchautor mal ne Mail, dass das mit der statischen Eigenschaft nicht hinhaut. Wird er sicher korrigieren wollen. Thanks 🙂



  • Jürgen Wolf?

    😞



  • Also wenn man bedenkt, dass das Buch 10,20 € kostet, ist es absolut unschlagbar! 🙂



  • Was nützt es ein paar Kröten gespart zu haben, wenn du damit völlig verkorkstes C++ lernst und dein ganzes Leben daran leidest?


Anmelden zum Antworten