2010-08-14 24 views
13

Estoy repasando el tutorial completo en cplusplus.com, codificando y compilando cada ejemplo manualmente. Regularmente, me tropiezo con algo que me deja perplejo.¿Cuál es la diferencia entre función (myVar) y (función) myVar?

Actualmente estoy aprendiendo esta sección: http://www.cplusplus.com/doc/tutorial/structures/. Hay algunas sutilezas que podrían pasarse por alto simplemente leyendo el tutorial. La ventaja de escribir todo a mano es que tales detalles se destacan.

En la página anterior, hay dos programas de muestra. Uno tiene esta línea:

stringstream(mystr) >> yours.year; 

El otro tiene esta línea:

(stringstream) mystr >> pmovie->year; 

Lo que no entiendo es la diferencia (si la hay) entre function (myVar) = x; y (function) myVar = x;.

No estoy haciendo todo el tutorial en orden secuencial. Lo revisé, pero no encontré esto abordado en ningún lado, aunque es posible que me lo haya perdido.

  • ¿Hay alguna diferencia?
  • ¿Hay alguna forma de hacerlo de una manera y no de la otra?
+12

no es una función, sino una clase. la primera llamada es una llamada de constructor, la segunda es una llamada de operador de conversión. – KeatsPeeks

Respuesta

55

No hay diferencia entre type(x) y (type)x.Estos dos son completamente equivalentes. La mayoría de la gente prefiere type(x) para las clases y (type)x para los tipos que no son de clase, pero eso es puramente de su propia elección. Ambos llaman constructores para clases con un argumento x.

La forma preferida para las clases es type(x), porque esto permite pasar más de un argumento al constructor, como en type(x, y). Si intenta aplicar el otro formulario, (type)x, y no funcionará: arroja x, y luego aplica el operador de coma y evalúa y de forma aislada. Los paréntesis como (type)(x, y) no ayudan: Esto evaluará x y y de forma aislada utilizando el operador de coma y luego emitirá y a y a type.

Para los tipos que no son de clase, este tipo de conversión suele ser demasiado potente. C++ tiene static_cast<type>(x) por realizar aproximadamente el reverso de una conversión implícita (como lanzar clases base a clases derivadas y emitir void* a otro puntero), que a menudo es lo que encaja. Véase When should static_cast, dynamic_cast and reinterpret_cast be used?.

stringstream no es una función, sin embargo. Hacer function(x) lo llamará la función, pero hacer (function)x es ilegal, porque hay dos expresiones una al lado de la otra, sin operador en el medio.


Para aquellos que no creen esta respuesta, y Downvote en primera impresión, consulte la Norma en el 5.2.3/1

Un simple de tipo especificador (7.1.5) seguido de una la lista de expresiones entre paréntesis construye un valor del tipo especificado dada la lista de expresiones. Si la lista de expresiones es una sola expresión, la expresión de conversión de tipos es equivalente (en definición, y si se define en el significado) a la expresión de conversión correspondiente (5.4).

+0

No diría que es solo un método de estilo de codificación: uno es un elenco, el otro es una llamada de constructor, son dos conceptos diferentes. – nico

+1

@nico no es una cuestión de opinión. El Estándar define lo que es equivalente y lo que no. Define estos dos como equivalentes, por lo que depende de los estilos de codificación decir qué se usa y en qué caso. –

+0

Generan resultados equivalentes, eso no significa que sean la misma cosa, y de hecho el estándar no dice que son iguales, solo que sus resultados son equivalentes. Probablemente sea una cuestión de semántica, pero creo que esta pregunta es sobre semántica. – nico

4

La página que cita no es lo que yo consideraría una autoridad en C++ en general.

De todos modos,

(stringstream) mystr >> pmovie-> año;

arroja un std::string a un objeto std::stringstream. Este es un elenco estilo C Bastante peligroso si no sabes lo que estás haciendo. Esto crearía un objeto stringstream y el valor se extraería a pmovie->year a continuación.

stringstream (mystr) >> yours.year;

Crea un std::stringstream objeto anónimo y lo inicializa con mystr y entonces el valor se extrae a pmovie->year. El objeto desaparece al final de su alcance léxico, que en este caso sería el ; al final de la línea.

No hay mucha diferencia (como otros lo han notado hasta ahora) entre los dos objetos de la clase w.r.t.

Por otro lado, con los identificadores (de funciones/macros) esto se vuelve complicado: function (myVar) = x; funciona independientemente de si function es una función real o una macro. Sin embargo, (function) (myVar) = x; solo funciona para funciones reales.

Algunos identificadores de biblioteca estándar pueden tener ambas formas (más notablemente, el tolower y amigos) y, por lo tanto, si desea invocar la función siempre, entonces debe elegir la primera.

+1

¿Qué ocurre con cplusplus.com? Uso su referencia todo el tiempo. – rubenvb

+1

Es una opinión personal, por supuesto. Y la pregunta de OP es un buen ejemplo. – dirkgently

+1

Su respuesta sugiere que hay una diferencia entre ambas formas, pero no detalla esa diferencia. También sugiere que la expresión mal formada '(función) myVar' sería válida (en oposición a' (función) (myVar) '). –

Cuestiones relacionadas