2009-09-04 16 views
9

Echa un vistazo aquí: En el siguiente código, ¿cuál sería el tipo de b?truco pregunta con respecto a sintaxis de declaración en C++

struct A { 
    A (int i) {} 
}; 

struct B { 
    B (A a) {} 
}; 

int main() { 
    int i = 1; 
    B b(A(i)); // what would be the type of b 
    return 0; 
} 

Voy a apreciar que si alguien podría explicarme bien ¿por qué existir tales sintaxis :)

Gracias.

Respuesta

7

Una de las verrugas de C (y C++ la hereda (y lo empeora)) es que no hay una sintaxis especial para presentar una declaración. Esto significa que las declaraciones a menudo se ven como código ejecutable. Otro ejemplo:

A * a; 

¿Está esto multiplicando A por a, o está declarando algo? Para darle sentido a esta línea, debes saber que A es el nombre de un tipo.

La regla básica en C++ es que si algo se puede analizar como una declaración, lo es. En este caso, conduce a un resultado extraño y sorprendente. Las declaraciones de funciones se parecen mucho a las llamadas a funciones y, en particular, la (después de que A se puede pensar de dos maneras:

Puede solucionar esto en este ejemplo con paréntesis adicionales que eliminan la capacidad del compilador para analizar el código como una declaración.

B b((A(i))); 

En C no es ambigua, porque no hay un estilo en función de llamada al constructor porque no hay constructores. una es el nombre de un tipo, o que es el nombre de una función . No puede ser ambos.

+2

creo que también se podría do: B b = B (A (i)); – Bill

+0

Sí, eso también funcionaría, es más fácil de entender y menos feo. :-) – Omnifarious

+2

... pero significa una cosa diferente - 'B b = B (...)' requiere 'B' para tener un constructor de copia (aunque el compilador puede optimizar la llamada, sigue siendo necesario) para comprobar), mientras que 'B b (...)' no lo requiere. –

7

Es una declaración de función local según C++ Standard 8.2/1. Se podría utilizar forma implícita de constructor para evitar esto o lo siguiente:

B b(A(i)); // is equal to B b(A i); 

// --- 

// to declare variable of type B write: 
B b = A(i); 
// explicit form if you want: 
B b(static_cast<A>(A(i))); 
// or 
B b((A)i); 

C++ estándar 8.2/1:

La ambigüedad que surge de la similitud entre una conversión de estilo de función y una declaración mencionada en el 6.8 también puede ocurrir en el contexto de una declaración. En ese contexto, la elección es entre una declaración de función con un conjunto redundante de paréntesis alrededor de un nombre de parámetro y una declaración de objeto con un estilo de función emitido como el inicializador. Al igual que para las ambigüedades mencionadas en 6.8, la resolución es considerar cualquier estructura que pueda ser una declaración.

5
B b(A(i)); 

es equivalente a

B b(A i); 

- el paréntesis alrededor del nombre de argumento son opcionales -, que es equivalente a

B b(A); 

- el nombre del parámetro es opcional en las declaraciones de función. Por lo tanto, es una declaración de función.

Normalmente se ejecutan en él con

X x(); 

- no por defecto constructor como se esperaba -, pero hay casos más complicados cuando se utilizan los temporales hasta el final, por ejemplo

vector<int> v(istream_iterator<int>(cin), istream_iterator<int>()); 
+0

Inesperadamente, se convirtió en un buen argumento contra 'using namespace' :) –

+0

Lamentablemente, va más allá de eso. Si cin hubiera sido std :: cin, entonces GCC determina que esta línea de hecho construye un objeto vector, mientras que VC++ (2005) se queja de que std :: cin no puede aparecer como nombre de parámetro. – UncleBens

+0

@UncleBens, Desafortunadamente, GCC está equivocado con eso y VC++ es correcto. Ver mi informe de defectos para clang: http://llvm.org/bugs/show_bug.cgi?id=4594 –

Cuestiones relacionadas