2016-02-18 8 views
9

Ich bin mir bewusst, dass die verschiedenen Guss Operatoren in C++ bereits hier diskutiert oft haben aber meine Frage ist speziell über zwischen numerischen Typen Gießen, nicht über die allgemeinen Unterschiede zwischen C-Stil und C++ Stiloperatoren. Ich halte dies für ein völlig anderes Thema als das Gießen innerhalb einer Klassenhierarchie.C++ Gießen zwischen numerischen Typen

sagen, ich will eine int i zu einem Doppel werfen, einige der Optionen ich habe, sind

static_cast<double>(i) 
(double) i 
double(i) 

Persönlich bevorzuge ich den Konstruktor-Stil in der 3. Zeile in diesem Fall, weil ich zum Ausdruck bringen, dass es sich hierbei nicht um eine Klasse von Gussklassen handelt, bei denen ich sicherlich static_cast oder dynamic_cast verwenden würde.

Abgesehen davon, dass es schwierig ist, diese Art von Cast bei der Suche in einem Texteditor zu finden, gibt es irgendwelche Nachteile meiner Wahl?

+1

Was ist der Kontext? Warum musst du spielen? –

+0

@Karoly Horvath: Gute Frage, ich versuche immer, Umwandlungen zu vermeiden, aber typische Fälle, in denen ich dies tue, sind innerhalb von Berechnungen oder beim Übergeben von Funktionsargumenten. –

+4

"schwierig zu finden diese Art von Besetzung" ist ein Grund genug, es nie zu benutzen. –

Antwort

4

static_cast<double>(i) ist sicherlich der klarste Ausdruck Ihrer Absicht in diesem speziellen Fall.

Wenn Sie zwischen numerischen Typen umwandeln, sind Sie oft einen Steinwurf von undefiniertem Verhalten entfernt. Sei also vorsichtig im Allgemeinen. Obwohl Ihr Cast für jeden möglichen Wert von i definiert ist, konnte ein double an einen int Überlauf der int übergeben werden, und dieses Verhalten ist in C++ undefiniert.

Ich würde immer Ihre Überprüfung empfehlen, wenn der Zieltyp den Quellentyp aufnehmen kann. std::numeric_limits<>::max() usw. kann hier helfen.

Der C++ - Standard gibt keine maximale Größe von int an (obwohl 16, 32 und 64-Bit-Zweierkomplement üblich sind), daher ist es möglicherweise nicht als double darstellbar.

In meinem Code habe ich einen Namespace

template< 
     typename T/*the desired type*/, 
     typename/*the source type*/ Y 
    > T integral_cast(const Y& y) 
    { 
     static_assert(false, "undefined integral_cast"); 
    } 

die ich spezialisiert für jede numerische Besetzung enthält ich brauche.

+2

'static_cast' wird Sie hier nicht vor undefiniertem Verhalten schützen. Und das OP gab in diesem speziellen Fall einen sehr guten Punkt für ihre bevorzugte Besetzung. – StoryTeller

+0

In der Tat, aber es ist eine sehr klare Art, es zu schreiben. Beachten Sie jedoch, dass das Casting von einem "int" zu einem "double" * immer * definiert ist. – Bathsheba

+0

Das ist die Meinung basiert. Es steht sicherlich mehr heraus, aber die Vorstellung, aus einem "Int" ein neues "Double" zu konstruieren, ist ebenfalls sehr klar. – StoryTeller

3

Ein Hauptnachteil dieser Ansätze ist, dass der Cast nicht gegen Überläufe und andere numerische Fehler sicher ist.

Mit static_cast ist die sofortige gesunde Lösung und diese Methode wird nicht von statischen Code-Analyse-Tools wie PVS studio gekennzeichnet. Der (double)i Ansatz erzeugt eine Warnung.

Wahrscheinlich ist die sicherste Methode ist, Ihre eigene Guss haben sagen wir mal, numeric_cast<T>()

template <class OT, class ST> 
OT numeric_cast(const ST value) 
{ 
    return static_cast<OT>(value); 
} 

Der Vorteil dieser Funktion ist, dass Sie verpflichtet, Kontrollen tun können, und andere numerische Kontrollen, um sicherzustellen, dass die Besetzung legitim ist und nicht Rückgabe (oder erhalten) Junk-Werte.

Es gibt eine andere Möglichkeit, mit Zahlen umzugehen, aber sie funktioniert nur mit konstanten Werten für die Kompilierzeit. Für diese Prüfung user defined string literals

Verwandte Themen