2010-08-14 7 views
13

Ich gehe durch das vollständige Tutorial bei cplusplus.com, codieren und kompilieren jedes Beispiel manuell. Regelmäßig stolpere ich über etwas, das mich perplex lässt.Was ist der Unterschied zwischen Funktion (myVar) und (Funktion) myVar?

Ich lerne gerade diesen Abschnitt: http://www.cplusplus.com/doc/tutorial/structures/. Es gibt einige Feinheiten, die leicht übersehen werden könnten, wenn man nur das Tutorial liest. Der Vorteil, alles von Hand zu tippen, ist, dass solche Details hervorstechen.

In der obigen Seite gibt es zwei Beispielprogramme. Man hat diese Zeile:

stringstream(mystr) >> yours.year; 

Der andere hat diese Zeile:

(stringstream) mystr >> pmovie->year; 

Was ich nicht verstehen ist der Unterschied (falls vorhanden) zwischen function (myVar) = x; und (function) myVar = x;.

Ich mache nicht das ganze Tutorial in der Reihenfolge. Ich habe es überprüft, aber ich habe es nirgends gefunden, obwohl ich es vielleicht übersehen habe.

  • Gibt es einen Unterschied?
  • Gibt es einen bevorzugten Weg, es in eine Richtung und nicht in die andere zu tun?
+12

es ist keine Funktion, aber eine Klasse. Der erste Aufruf ist ein Konstruktoraufruf, der zweite Aufruf ist ein Konvertierungsoperatoraufruf. – KeatsPeeks

Antwort

55

Es gibt keinen Unterschied zwischen type(x) und (type)x.Diese beiden sind völlig gleichwertig. Die meisten Leute bevorzugen type(x) für Klassen und (type)x für Nicht-Klassen-Typen, aber das ist rein bis zu einer eigenen Wahl. Beide rufen Konstruktoren für Klassen mit einem Argument x auf.

Der bevorzugte Weg für Klassen ist type(x), weil dadurch mehr als ein Argument an den Konstruktor übergeben werden kann, wie in type(x, y). Wenn Sie versuchen, das andere Formular anzuwenden, wird (type)x, y nicht funktionieren: Es wird x, und dann den Komma-Operator und Evaluierungen y isoliert angewendet. Klammern wie (type)(x, y) helfen nicht: Dadurch werden x und y isoliert mit dem Komma-Operator ausgewertet und dann y an type.

Für Nicht-Klassen-Typen ist eine solche Besetzung oft zu leistungsfähig. C++ hat static_cast<type>(x) für grob die Umkehrung einer impliziten Konvertierung (wie Casting Basisklassen zu abgeleiteten Klassen und Casting void* zu einem anderen Zeiger), was oft was passt. Siehe When should static_cast, dynamic_cast and reinterpret_cast be used?.

stringstream ist jedoch keine Funktion. Doing function(x) wird es die Funktion nennen, aber (function)x zu tun ist illegal, weil es zwei Ausdrücke nebeneinander gibt, ohne Operator dazwischen.


Für diejenigen, die diese Antwort nicht glauben, und es auf downvote Bauchgefühl, konsultieren Sie bitte den Standard der 5.2.3/1

Ein einfacher-Typ-Spezifizierer (7.1.5), gefolgt von einem Die in Klammern gesetzte Ausdruckliste erstellt einen Wert des angegebenen Typs in der Ausdrucksliste. Wenn die Ausdrucksliste ein einzelner Ausdruck ist, ist der Typkonvertierungsausdruck dem definierten Ausdruck (5.4) äquivalent (definiert und wenn definiert).

+0

Ich würde nicht sagen, es ist nur eine Metter der Codierung Stil: eine ist eine Besetzung der andere ist ein Konstruktor Aufruf, sie sind zwei verschiedene Konzepte. – nico

+1

@nico ist keine Meinungssache. Der Standard definiert, was gleichwertig ist und was nicht. Es definiert diese beiden als äquivalent, es liegt also an Codierungsstilen zu sagen, was in welchem ​​Fall verwendet wird. –

+0

Sie erzeugen äquivalente Ergebnisse, das bedeutet nicht, dass sie das Gleiche sind, und tatsächlich sagt der Standard nicht, dass sie gleich sind, nur dass ihre Ergebnisse äquivalent sind. Wahrscheinlich eine Frage der Semantik, aber ich denke, diese Frage betrifft die Semantik. – nico

4

Die Seite, die Sie anführen, ist nicht das, was ich als Autorität in C++ im Allgemeinen betrachten würde.

Wie dem auch sei,

(string) mystr >> pmovie-> Jahr;

überträgt ein std::string auf ein std::stringstream Objekt. Dies ist ein C-Style-Cast. Eher gefährlich, wenn Sie nicht wissen, was Sie tun. Dies würde ein Objekt stringstream erstellen und der Wert wird als Nächstes in pmovie->year extrahiert.

stringstream (meinstr) >> yours.year;

Erzeugt ein anonymes std::stringstream Objekt und initialisiert es mit mystr und dann wird der Wert auf pmovie->year extrahiert. Das Objekt verschwindet am Ende seines lexikalischen Umfangs, der in diesem Fall am Ende der Zeile ; wäre.

Nicht viel Unterschied (wie andere bisher bemerkt haben) unter den zwei w.r.t-Klassenobjekten.

Auf der anderen Seite, mit Kennungen (von Funktionen/Makros) wird dies schwierig: function (myVar) = x; funktioniert unabhängig davon, ob function eine tatsächliche Funktion oder ein Makro ist. (function) (myVar) = x; funktioniert jedoch nur für echte Funktionen.

Einige Standard-Bibliotheks-IDs dürfen beide Formen haben (vor allem die tolower und Freunde). Wenn Sie die Funktion also immer aufrufen möchten, sollten Sie die erste verwenden.

+1

was ist falsch mit cplusplus.com? Ich benutze ihre Referenz die ganze Zeit. – rubenvb

+1

Es ist natürlich eine persönliche Meinung. Und die Frage des OP ist ein typisches Beispiel. – dirkgently

+1

Ihre Antwort schlägt vor, dass es einen Unterschied zwischen beiden Formen gibt, aber diesen Unterschied nicht detailliert. Es schlägt auch vor, dass der schlecht gebildete Ausdruck "(Funktion) myVar" gültig wäre (im Gegensatz zu "(Funktion) (myVar)"). –

Verwandte Themen