Typumwandlung durch Operatoren Codeverständnis



  • Hallo,

    ich folge grade einem Anfängerkurs in C++ und habe leider ein Verständnisproblem an einer kaum dokumentierten Stelle. Hier zunächst einmal der Code:

    class Bruch {
    public :
    explicit Bruch ( int x = 0 , int y = 1){ p_x = x ; p_y = y ; }
    operator double () const {
    return ( double ) ( p_x / p_y );
    }
    private :
    int p_x , p_y ; // Zähler und Nenner
    int main () {
    Bruch x (5 , 2);
    double y ;
    y = x * 15;  // x - > double
    y = 10 * x ; // hier auch möglich x - > double
    return 0;
    }
    

    Soweit ich das verstanden habe erhält der Operator immer das linke Objekt automatisch als Zeiger, das rechte optional per expliziter Übergabe. Diese Theorie passt allerdings nicht zu dem Beispiel. #
    Als Erlärung wurde angegeben das x mittels des Operators von Bruch nach double umgewandelt wird.
    Kann mir jemand erklären wie der Code funktioniert? Ich habe mich jetzt eine halbe Stunde damit beschäftigt, kommt aber nicht weiter.



  • Da es hier keinen definierten "operator *(Bruch, double)" gibt, aber den "operator double () const", führt der Compiler eine Typumwandlung (cast) hier durch, so als ob folgendes im Code stehen würde:

    y = (double)x * 15; // x - > double
    y = 10 * (double)x; // hier auch möglich x - > double
    

    Edit: Und dann werden jeweils 2 double-Multiplikationen durchgeführt.


  • Mod

    Mit den offensichtlichen Syntaxkorrekturen:

    class Bruch {
    public :
        explicit Bruch ( int x = 0 , int y = 1){ p_x = x ; p_y = y ; }
        operator double () const {
            return ( double ) ( p_x / p_y ); // der Cast kommt zu spät, die Division wurde bereits als Ganzzahldivision durchgeführt
                                             // nur das Ergebnis wird nachträglich nach double konvertiert (das würde aber auch implizit passieren)
        }
    private :
        int p_x , p_y ; // Zähler und Nenner
    };
    int main () {
        Bruch x (5 , 2);
        double y ;
        y = x * 15;  // x ist int, 15 ist ein int => Multiplikation erfolgt als int, umgewandelt wird erst bei der Zuweisung des Multiplikationsergebnisses
        y = 10 * x ; // dito
        return 0;
    }
    


  • Wie kommst du darauf: "x ist int"?
    OK, daß die Division im operator double() falsch ist, hatte ich vorher nicht gesehen, trotzdem wird ja ein double-Wert zurückgegeben, so daß wegen der Promotion bei der Multiplikation implizit der andere Operand (d.h. der int-Wert) in ein double umgewandelt wird.

    Die Namensgebung im Code ist natürlich suboptimal, da x doppelt für 2 verschiedene Typen benutzt wird (int und Bruch).


  • Mod

    Th69 schrieb:

    Wie kommst du darauf: "x ist int"?

    Mein Fehler. p_x != x
    Leicht zu verwechselnde Namen sind aber dem TE anzulassten.

    Also richtig:

    class Bruch {
    public :
        explicit Bruch ( int x = 0 , int y = 1){ p_x = x ; p_y = y ; }
        operator double () const {
            return ( double ) ( p_x / p_y ); // der Cast kommt zu spät, die Division wurde bereits als Ganzzahldivision durchgeführt
                                             // nur das Ergebnis wird nachträglich nach double konvertiert (das würde aber auch implizit passieren)
        }
    private :
        int p_x , p_y ; // Zähler und Nenner
    };
    int main () {
        Bruch x (5 , 2);
        double y ;
        y = x * 15;  // x ist ein Bruch, es existiert kein überladener op*, der ein Bruch als linken Operanden nimmt.
                     // Der eingebaute Operator* ist anwendbar, da eine eindeutige Konvertierung in einen arithmetischen Typ (double) existiert
                     // die gewöhnlichen arithmetischen Konvertierungen sorgen dann dafür, dass auch der rechte Operand zu double konvertiert wird
        y = 10 * x ; // ditto
        return 0;
    }
    


  • 👍


Log in to reply