2010-08-14 6 views
13

Je suis en train de suivre le tutoriel complet sur cplusplus.com, codant et compilant chaque exemple manuellement. Régulièrement, je tombe sur quelque chose qui me laisse perplexe.Quelle est la différence entre function (myVar) et (function) myVar?

J'étudie actuellement cette section: http://www.cplusplus.com/doc/tutorial/structures/. Il y a quelques subtilités qui pourraient facilement être négligées en lisant seulement le tutoriel. L'avantage de tout taper à la main est que ces détails se démarquent.

Dans la page ci-dessus, il y a deux exemples de programmes. On a cette ligne:

stringstream(mystr) >> yours.year; 

L'autre a cette ligne:

(stringstream) mystr >> pmovie->year; 

Ce que je ne comprends pas la différence (le cas échéant) entre function (myVar) = x; et (function) myVar = x;. Je ne fais pas tout le tutoriel dans un ordre séquentiel. J'ai vérifié mais je n'ai pas trouvé cela adressé nulle part, même si j'ai peut-être raté.

  • Y a-t-il une différence?
  • Existe-t-il un moyen préféré de le faire dans un sens plutôt que dans l'autre?
+12

ce n'est pas une fonction, mais une classe. le premier appel est un appel de constructeur, le second est un appel d'opérateur de conversion. – KeatsPeeks

Répondre

55

Il n'y a pas de différence entre type(x) et (type)x.Ces deux sont complètement équivalents. La plupart des gens préfèrent type(x) pour les classes et (type)x pour les types non-classe, mais c'est purement à son propre choix. Les deux appellent des constructeurs pour des classes avec un argument x.

La méthode préférée pour les classes est type(x), car cela permet de transmettre plus d'un argument au constructeur, comme dans type(x, y). En essayant d'appliquer l'autre forme, (type)x, y ne fonctionnera pas: Il lance x, puis applique l'opérateur de virgule et évalue y de manière isolée. Les parenthèses comme (type)(x, y) n'aident pas: cela évaluera x et y isolément à l'aide de l'opérateur virgule, puis lancera y en type.

Pour les types hors classe, une telle distribution est souvent trop puissante. C++ a static_cast<type>(x) pour faire l'inverse d'une conversion implicite (par exemple lancer des classes de base à des classes dérivées et transtyper void* en un autre pointeur), ce qui correspond souvent à ce qui convient. Voir When should static_cast, dynamic_cast and reinterpret_cast be used?.

stringstream n'est pas une fonction, cependant. Faire function(x) l'appellera la fonction, mais faire (function)x est illégal, car il y a deux expressions l'une à côté de l'autre, sans opérateur entre les deux.


Pour ceux qui ne croient pas cette réponse, et downvote sur le sentiment de l'intestin, s'il vous plaît consulter la norme à 5.2.3/1

A-type spécificateur simple (7.1.5) suivi d'un parenthesized expression-list construit une valeur du type spécifié en fonction de la liste d'expressions. Si la liste d'expressions est une expression unique, l'expression de conversion de type est équivalente (en définition et si elle est définie dans son sens) à l'expression de conversion correspondante (5.4).

+0

Je ne dirais pas que c'est juste un code de style de codage: l'un est un cast, l'autre est un appel de constructeur, ce sont deux concepts différents. – nico

+1

@nico ce n'est pas une question d'opinion. La norme définit ce qui est équivalent et ce qui ne l'est pas. Il définit ces deux comme équivalents, il revient donc aux styles de codage de dire ce qui est utilisé dans quel cas. –

+0

Ils génèrent des résultats équivalents, cela ne veut pas dire qu'ils sont la même chose, et en fait la norme ne dit pas qu'ils sont identiques, juste que leurs résultats sont équivalents. Probablement une question de sémantique, mais je pense que cette question concerne la sémantique. – nico

4

La page que vous citez n'est pas ce que je considère comme une autorité sur C++ en général.

Quoi qu'il en soit,

(stringstream) mystr >> pmovie-> année;

envoie un std::string à un objet std::stringstream. C'est un casting de style C. Plutôt dangereux si vous ne savez pas ce que vous faites. Cela crée un objet stringstream et la valeur est extraite à pmovie->year ensuite.

stringstream (mystr) >> votre.année;

Crée un objet std::stringstream anonyme et initialise avec mystr et la valeur est extraite à pmovie->year. L'objet disparaît à la fin de sa portée lexicale qui dans ce cas serait le ; à la fin de la ligne.

Pas beaucoup de différence (comme d'autres l'ont noté jusqu'à présent) parmi les deux objets de classe w.r.t. D'autre part, avec des identifiants (de fonctions/macros) cela devient compliqué: function (myVar) = x; fonctionne indépendamment du fait que function soit une fonction réelle ou une macro. Cependant, (function) (myVar) = x; ne fonctionne que pour les fonctions réelles.

Certains identifiants de bibliothèque standard sont autorisés à avoir les deux formes (plus particulièrement le tolower et amis) et donc si vous souhaitez invoquer la fonction toujours alors vous devriez aller pour le premier.

+1

quoi de mal avec cplusplus.com? J'utilise leur référence tout le temps. – rubenvb

+1

C'est une opinion personnelle, bien sûr. Et la question du PO est un bon exemple. – dirkgently

+1

Votre réponse suggère qu'il existe une différence entre les deux formes, mais ne précise pas cette différence. Il suggère également que l'expression mal formée '(fonction) myVar' serait valide (par opposition à' (function) (myVar) '). –

Questions connexes