2011-09-30 20 views
11

Estoy un poco confundido después de leer algo en un libro de texto. En cuanto al código:¿Es esto un yeso o una construcción?

void doSomeWork(const Widget& w) 
{ 
    //Fun stuff. 
} 

doSomeWork(Widget(15)); 

doSomeWork() toma un parámetro const Widget&. El libro de texto, Effective C++ III, establece que esto crea un objeto Widget temporal para pasar a doSomeWork. Se dice que este puede ser reemplazado por:

doSomeWork(static_cast<Widget>(15)); 

ya que ambas versiones son moldes - la primera es sólo una conversión de estilo de función C al parecer. Yo hubiera pensado que Widget(15) invocaría un constructor para el widget tomando un parámetro entero.

¿Se podría ejecutar el constructor en este caso?

Respuesta

12

En C++ este tipo de expresión es una forma de un elenco, al menos sintácticamente. Es decir. utiliza una sintaxis de molde funcional C++ Widget(15) para crear un objeto temporal de tipo Widget.

Incluso cuando se construye un temporal utilizando un constructor de múltiples argumento (como en Widget(1, 2, 3)) todavía se considera una variación de funcional notación fundido (ver 5.2.3)

En otras palabras, su "¿Es esta pregunta de "yeso o construcción" está incorrectamente establecida, ya que implica exclusividad mutua entre moldes y "construcciones". No son mutuamente exclusivos. De hecho, cada conversión de tipo (ya sea un molde explícito o algo más implícito) no es más que una creación ("construcción") de un nuevo objeto temporal del tipo de destino (excluyendo, tal vez, algunas inicializaciones de referencia).

Por cierto, la notación de lanzamiento funcional es principalmente una notación de C++. El lenguaje C no tiene moldes de estilo funcional.

1

Usted dijo:

el primero es sólo una conversión de estilo de función C aparentemente

El primero no compile los en C, no es C-estilo. El estilo C se ve como (Widget)15. Aquí, el objeto temporal se crea usando Widget::Widget(int).

Por lo tanto, no es un elenco de estilo C.

+1

@Constantinius: ¿Qué hay de malo aquí? – AnT

+0

He editado su respuesta. –

-1

Yeeeah. Puede reemplazar

Widget(15) 

con

static_cast<Widget>(15) 

, ya que será reemplazado por el compilador de vuelta: D

Cuando lanzas int a Widget compilador busca Widget::Widget(int); y colocarlo allí.

5

Corto: Sí.

larga:

Siempre se puede probar esas cosas a sí mismo, haciendo ej .:

#include <iostream> 

struct W 
{ 
    W(int i) 
    { 
     std::cout << "W(" << i << ")\n"; 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
    W w(1); 
    W(2); 
    static_cast<W>(3); 
} 

que está dando salida a

W(1) 
W(2) 
W(3) 
+0

El primero no es un elenco. ¿Qué intentaste mostrar? – MSalters

+2

@MSalters: para la mayoría de los tipos, un molde no es diferente de crear un objeto (temporal). – PlasmaHH

+1

@MSalters: creo que estaba tratando de mostrar la diferencia –

3

Sí, es a la vez :). Un elenco es una construcción sintáctica (es decir, algo que escriba). En este caso, se invoca un constructor como consecuencia del lanzamiento. Al igual que un constructor se invocaría como consecuencia de escribir

Widget w(15); 
3

Tanto Widget(15) y static_cast<Widget>(15) son yesos, o conversión operadores, si lo prefiere. Ambos crean un nuevo objeto del tipo designado , al convertir 15 en Widget. Como 15 no tiene ningún operador de conversión , la única forma de realizar esta conversión es mediante asignando la memoria necesaria (en la pila) y llamando al constructor apropiado . Esto no es realmente diferente que double(15) y static_cast<double>(15), excepto que por lo general no piensan de double como tener un constructor (pero el double resultante es una nueva objeto, distinta de la 15, que tiene el tipo int).

0

Sí, por supuesto. Cualquier constructor que tome un solo parámetro se consideraría CONSTRUCTOR DE CONVERSIÓN. Su constructor ya está tomando un único parámetro int, de modo que el compilador puede llamar "implícitamente" a este constructor para que coincida con el argumento (con el valor 15, que es int).

Hay un truco simple para evitar tales errores, simplemente use la palabra clave explicit antes de su constructor.

Compruebe this para obtener más información.