2008-10-07 21 views
159

¿Hay alguna buena razón para que un conjunto vacío de corchetes (paréntesis) no sea válido para llamar al constructor predeterminado en C++?Constructor predeterminado con corchetes vacíos

MyObject object; // ok - default ctor 
MyObject object(blah); // ok 

MyObject object(); // error 

Parece que escribo "()" automáticamente cada vez. ¿Hay alguna buena razón por la que esto no está permitido?

+0

Alguien debería venir con un mejor título para esto, pero no puedo pensar en lo que sería. Al menos deletree "constructor" para ayudar a los motores de búsqueda. –

+1

Y este es solo otro buen ejemplo donde C++ es sensible al contexto. El código de ejemplo en la pregunta también fallaría si 'blah' fuera una clase. – Albert

Respuesta

131

de análisis más acuciantes

Esto se relaciona con lo que se conoce como "análisis sintáctico más irritante C++ 's". Básicamente, cualquier cosa que pueda ser interpretada por el compilador como una declaración será interpretada como una declaración.

Otro ejemplo del mismo problema:

std::ifstream ifs("file.txt"); 
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>()); 

v se interpreta como una declaración de la función con 2 parámetros.

La solución consiste en añadir otro par de paréntesis:

std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>()); 

O, si usted tiene 11 C++ y la lista de inicialización (también conocida como la inicialización uniforme) disponibles:

std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}}; 

Con esto, no hay forma de que pueda ser interpretado como una declaración de función.

+0

He leído STL eficaz pero no recuerdo haberlo visto. tendré que volver a leerlo, gracias –

+6

Nitpick: puedes declarar funciones dentro de las funciones. Se llama _funciones locales_ en C, y al menos 'extern" C "foo();' -style también está permitido en C++. –

+0

Gracias, mmutz, no sé lo que estaba pensando cuando lo escribí, probablemente confunde la declaración con la definición. Editó la respuesta en consecuencia. – Constantin

50

La misma sintaxis se utiliza para la declaración de funciones, p. Ej. la función object, no toma ningún parámetro y devuelve MyObject

+1

Gracias - no se me ocurriría declarar una función en el emiddle de algún otro código. Pero supongo que es legal. –

10

Porque el compilador cree que es una declaración de una función que no toma argumentos y devuelve una instancia de MyObject.

81

porque es el tratado como la declaración de una función:

int MyFunction(); // clearly a function 
MyObject object(); // also a function declaration 
+7

En realidad prefiero esto a la respuesta exceptuada, es mucho más claro en cuanto a cuál es la causa del problema – thecoshman

4

supongo, el compilador no sabría si esta declaración:

objeto MiObjeto();

es una llamada a un constructor o un prototipo de función se declara una función llamada objeto con el tipo de retorno MiObjeto y sin parámetros.

4

Como he mencionado muchas veces, es una declaración. Es así para la compatibilidad con versiones anteriores. Una de las muchas áreas de C++ que son tontas/inconsistentes/dolorosas/falsas debido a su legado.

7

También es posible usar la forma más prolija de construcción:

MyObject object1 = MyObject(); 
MyObject object2 = MyObject(object1); 

En C++ 0x esto también permite auto:

auto object1 = MyObject(); 
auto object2 = MyObject(object1); 
+4

Esto requiere un constructor de copia y es ineficaz – Casebash

+9

@Casebash: El compilador es probablemente lo suficientemente inteligente como para usar alguna optimización de tipo 'RVO' que le impide ser ineficiente. – dalle

+1

"Probablemente" significa "estoy adivinando".Con respecto a la optimización, las personas generalmente no quieren adivinar, sino que toman el camino de manera explícita. – Stefan

2

De n4296 [DCL.init]:

[Nota:
Desde () no estén permitidas por la sintaxis para inicializador, X a(); no es la declaración de un objeto de clase X, pero la declaración de una función no toma ningún argumento y devuelve una X. El formulario () está permitido en ciertos otros contextos de inicialización (5.3.4, 5.2.3, 12.6.2).
-fin nota]

+2

¿Se puede agregar un enlace para la fuente? –

0

Como los otros dijo, se trata de una declaración de la función. Desde C++ 11 puede usar la inicialización de llaves si necesita ver el vacío, algo que explícitamente le dice que se usa un constructor predeterminado.

Jedi luke{}; //default constructor 
Cuestiones relacionadas