Typekonvertierung



  • Hallo

    #include <iostream>
    using namespace std;
    
    int main ()
    {
    
    double var  = 3.2;
    double var2 = 2.2;
    
    int var3 = 65;
    
    int z1;
    int z2;
    
    char z3;
    
    z1 = static_cast<int>(var);
    z2 = var2;        // wieso nicht gleich so konvertieren ?
    
    z3 = static_cast<long>(var3); // egal ob dort <double>, <char> , <float> oder so
                                  // steht ?
                                  // wieso wird int z4; nicht zu einem char ?
                                  // z3 ist immer A egal ob dort long , float , double
                                  // oder int steht
    
    cout<<"z1: "  <<z1 << endl;
    cout<<"z2: "   <<z2 <<endl;
    cout<<"z4: "   <<z3 <<endl;
    
    system("PAUSE");
    }
    //---------------------------------------------------------------------------
    


  • kon__ schrieb:

    // asc: auf das wesentliche gekürzt.
    double var  = 3.2;
    double var2 = 2.2;
    
    int z1;
    int z2;
    
    z1 = static_cast<int>(var);
    z2 = var2;        // wieso nicht gleich so konvertieren ?
    

    Stell mal die höchste Warnstufe an. double lässt sich nicht verlustfrei nach int konvertieren, und es sollte daher eine Warnung kommen (die man mittels expliziten static_cast unterdrückt). Zudem hat der cast auch den Vorteil, das man explizit sieht, das hier eine Konvertierung statt findet - was manche Fehlersuche vereinfachen kann.

    Auch deine restlichen Fragen erübrigen sich, wenn du wirklich mit höchster Warnstufe hantierst (Was man allgemein sollte, und das Ziel sollte sein dabei möglichst Warnungsfrei zu bleiben - oder falls nicht anders möglich [z.B. Fremdbibliotheken] Warnungen bewusst, und lokal abzuschalten - z.B. durch pragma-Anweisungen).



  • Wie ist das denn wenn man Daten von einem Datentyp in den nächsten kopiert so wie hier:

    int var1 = 30;
    int var2;
    
    var2 = var1;                 // So ??
    // var2 = static_cast<int>(var1);   Oder besser so ??
    
    cout << var2 << endl;
    

    Welche Variante ist hier besser die mit dem cast oder die mit der = Zuweisung ?

    Oder ist das in diesem Fall egal?



  • kon__ schrieb:

    Wie ist das denn wenn man Daten von einem Datentyp in den nächsten kopiert so wie hier:

    Innerhalb des gleichen Datentyps, oder von einem kleineren Datentyp in einen größeren, der diesen verlustfrei aufnehmen kann, ist niemals ein Cast erforderlich. Ein Cast wie static_cast weißt auf eine potentielle Problemstelle hin.

    Sprich: Ein expliziter Cast sollte dann gemacht werden, wenn es zu einem Verlust kommen kann, oder spezielle Umwandlungen nötig sind (ich erwähne hier nur mal dynamic_cast, reinterpret_cast... was aber hier zu weit führt), und man sollte sich der Konsequenzen bewusst sein. Allgemein ist ein C++ Cast aber weniger anfällig als ein C-Cast (dies nur am Rande, sprich ein static_cast<int>(a) ist einem (int)a im Zweifel vorzuziehen).



  • Diesen Satz verstehe ich nicht ganz:

    Ein expliziter Cast sollte dann gemacht werden, wenn es zu einem Verlust kommen kann,

    Was ist hier mit einem Verlust gemeint ?
    Hast du vielleicht ein beispiel dafür ?

    int var = 123456;
    short var_2;
    
    var_2 = var;  // Jetzt hätte man doch ein "Verlust" oder wie ist das gemeint ?
    


  • #include <iostream>
    using namespace std;
    
    int main ()
    {
    
    short var1 = 10;
    short var2 = 4;
    double result1, result2;
    
    result1 = var1 / var2;
    cout << result1<<endl; // result1 = 2  Verlust von 0.5
    
    result1 = static_cast<double>(var1) / static_cast<double>(var2);
    cout << result1<<endl;  // result1 = 2.5  Kein Verlust
    
    result1 = (double)var1 / (double)var2; // C-Style Typekonvertierung
    
    cout << result1<<endl;  // result1 = 2.5  Kein Verlust ( Kann aber ehr zum Verlust führen als
                           // bei static_cast ?
    
    system("PAUSE");
    }
    


  • Kann mir den keiner sagen ob ich das mit dem Verlust jetzt so richtig interpretiere oder nicht ?



  • kon__ schrieb:

    ...

    Gleich noch ein paar mehr Anmerkungen:
    1. Einrücken des Codes würde es einen Leser erleichtern. Ebenso solltest du Leerzeichen, etc. etwas einheitlicher setzen (z.B. mal lässt du einen Leerzeichen zwischen den operator<< und mal nicht).
    2. In C++ ist es üblich Variablen erst bei, oder direkt vor, der ersten Verwendung zu benutzen.

    Im ersten Fall, tritt der Verlust nicht durch die Zuweisung ein, sondern durch das Teilen (Erst werden zwei short geteilt, und danach das Ergebnis zugewiesen).

    Im zweiten Fall würde es theoretisch reichen, wenn du eine Seite umwandelst (da der Compiler die Typen für die Berechnung anpasst).

    Der Kommentar zum dritten stimmt nicht 100%ig. In diesen Fall ist der C-Style Cast unproblematisch. Der C-Style Cast macht aber deutlich mehr Umwandlungen mit, als der static_cast, und nicht alle sind vielleicht so gewünscht (Und schwer im Programmcode zu finden). In C++ gibt es aus diesen Gründen mehrere verschiedene Cast-Funktionen, die unterschiedliches ausdrücken. Mit den C-Style Cast kannst du im Wesentlichen Elefanten in Fliegen verwandeln, ohne eine Warnung zu erhalten, ob du das wünschst, sei dahin gestellt.



  • Nein, in dieser Hinsicht sind static_cast und der C-Cast äquivalent. Mit dem C-Cast kannst du aber (oft aus Versehen) sehr schräge Dinge casten, und dann hast du teilweise undefiniertes Verhalten. Darum würde ich eher zu den C++-Konvertierungsoperatoren raten, da ihre Funktionalität schön aufgetrennt ist und man sie gut im Code sieht.

    void Function(double* a, double* b)
    {
        int c = (int)a / (int)b; // Oh nein, sollte (int)*a / (int)*b heissen!
        // Hab ich nämlich nach dem Refactoring von Referenzen auf Zeiger vergessen
        // Aber es kompiliert ohne Probleme
    
        int c = static_cast<int>(a) / static_cast<int>(b);
        // Das wäre hier nicht passiert
    }
    
    void Function2(const BaseClass& b)
    {
        // Da ich weiss, dass es sich um eine Derived handelt, kann ich downcasten
        Function3( (DerivedClass&)b ); // Oh nein, const weggecastet!
        // Aber es kompiliert ohne Probleme
    
        Function3( static_cast<DerivedClass&>(b) );
        // Das wäre hier nicht passiert
    }
    
    void Function2(const BaseClass& b)
    // ein Monat später sind BaseClass und DerivedClass nicht mehr in einer Hierarchie
    {
        Function3( (const DerivedClass&)b ); // Ha, const diesmal richtig!
        // Oh nein, dafür aus Versehen zwei inkompatible Typen gleichgebogen
        // Aber es kompiliert ohne Probleme
    
        Function3( static_cast<DerivedClass&>(b) );
        // Das wäre hier nicht passiert
    }
    

    😉


Anmelden zum Antworten