2009-06-25 3 views
2

In C++ können Sie mehrere C-Casting- oder C++ - Casts werfen. Bjarne Stroustrup und viele andere C++ - Experten sagen, dass ein gutes Design kein Casting haben sollte.Wie komme ich vom Casting in C++ weg?

Kannst du mir helfen, den Code unten neu zu gestalten, um den Cast loszuwerden?

void CProgressBar::SetPosition(int nPos); //unable to change 

void CSaveDialog::UpdatePosition(double dProgress) 
{ 
    double percentOfProgress = dProgress * 100; 
    m_pProgressBar->SetPosition(static_cast<int>(percentOfProgress)); 
} 

Ich kann UpdatePosition ändern, aber nicht SetPosition.

+2

Wie ist es einfach, Int an UpdatePosition weiterzuleiten? –

+2

Das ist eine gute Frage, aber das Beispiel ist nicht repräsentativ für Stroustrups Bedeutung. Die Casting-Konversation würde einen völlig anderen Weg einschlagen, wenn Ihr Beispiel ein Basisklassenzeiger gegenüber einem abgeleiteten Klassenzeiger gewesen wäre. – Kieveli

Antwort

5

Ich denke, Casting in Arithmetik kann in Ordnung sein. Die Art von Casting, die wirklich vermieden werden sollte, ist auf und ab (oder quer durch) die eigene Klassenhierarchie.

Auch für Casting in Arithmetik möchten Sie wahrscheinlich vorsichtiger sein. Sie sollten wahrscheinlich ceil oder floor vor dem Gießen auf eine int anwenden. Ich bin mir nicht sicher, ob es komplett bestimmt ist, auf welche Weise ein Cast zu int runden wird. (also in Richtung + inf, in Richtung -inf oder in Richtung Null)

+1

Ich werde das bestätigen. Benutze einfach floor(), denn schließlich machst du von einem Double zu einem int - und floor() wurde genau dafür gebaut. –

+1

Es wird automatisch als Floor definiert: 4.9.1 "Ein rvalue eines Floating Point-Typs kann in einen rvalue eines Integer-Typs konvertiert werden. Die Konvertierung wird abgeschnitten, dh der Bruchteil wird verworfen." Persönlich bevorzuge ich es ohne den Boden. –

+0

Stock für positive Werte, das heißt :) Für negative Werte ist es eine Ceil –

3

Ich glaube nicht, dass die Besetzung notwendig ist, es gibt eine implizite Umwandlung von double in int. Comeau kompiliert das:

struct CProgressBar { 
    void SetPosition(int nPos); //unable to change 
}; 

struct CSaveDialog { 
    void UpdatePosition(double dProgress) 
    { 
    m_pProgressBar->SetPosition(dProgress * 100 ); 
    } 

    CProgressBar* m_pProgressBar; 
}; 

Ohne Fehler. Diese Art von cross-numerischen Umwandlungen wird erwartet, und deshalb gibt es implizite Umwandlungen zwischen ihnen.

+0

Aber dann verwenden Sie implizites Verhalten - der Leser Ihres Codes möglicherweise nicht einmal vermuten, eine Besetzung ist getan. – xtofl

+0

Es ist immer noch eine Besetzung beteiligt. Ihr Compiler erstellt es nur für Sie. Ich denke, da ist etwas in der Form von [int operator (int) (double d)] intrinsisch definiert. – KitsuneYMG

+1

@xtofl - Sie mögen keine Besetzung vermuten, aber ich denke nicht, dass sie das tun müssen. Zahlen "fließen" von einem Typ zum anderen. Außerdem macht es den Rest des Codes für UpdatePosition sauberer, einfacher zu lesen und robuster, da die implizite Umwandlung das Ergebnis der Funktionssignatur ist. Wenn sich die Funktionssignatur in float oder double ändert, führt dies zu korrektem Verhalten. –

1

Sie müssen nicht casten, Doppel werden automatisch in int gegossen, falls erforderlich. Sie sollten 0,5 zum Wert von dProgress hinzufügen, wenn Sie die Position einstellen, damit sie ordnungsgemäß gerundet wird. Wenn Sie double in int konvertieren, werden die Dezimalstellen abgeschnitten und nicht gerundet.

1

Machen Sie einfach percentOfProgress ein int.

1

Wenn Leute sagen, um Umwandlungen zu vermeiden, meinen sie normalerweise zwischen benutzerdefinierten Typen. Sie sollten zum Beispiel nicht sehr oft von einer Basisklasse auf die abgeleitete Klasse herabstufen müssen. Wenn Sie das brauchen, sollten Sie sich Ihre Klassenhierarchie genau ansehen und sehen, was damit nicht stimmt. Das gleiche gilt für reinterpret_cast. Wenn Sie dies häufig verwenden, um zwischen nicht miteinander verwandten Zeigertypen zu konvertieren, ist dies wahrscheinlich ein Zeichen dafür, dass Sie eine Low-Level-Bit-Hacker-Routine im C-Stil ausführen, die vermieden werden könnte und sollte.

Casting zwischen Int und Float oder andere numerische Typen, ist ziemlich zu erwarten.