steps - structure of c++
¿Cómo es posible usar esto en c++? (5)
Cuando escribes a a1();
en realidad se está analizando como una declaración de función, no como una llamada al constructor predeterminado.
a a1;
llamará al constructor predeterminado correctamente
Cuando escribas aa;
funciona porque el nombre de la variable tiene preferencia sobre el nombre de la clase en lo que se denomina ocultación del nombre, pero aunque funcione solo generará confusión y evitaría hacerlo.
Y para todas aquellas personas a las que les gustan los estándares, aquí van.
Un nombre de clase (9.1) o un nombre de enumeración (7.2) puede estar oculto por el nombre de una variable, miembro de datos, función o enumerador declarado en el mismo ámbito. Si una clase o nombre de enumeración y una variable, miembro de datos, función o enumerador se declaran en el mismo ámbito (en cualquier orden) con el mismo nombre, la clase o el nombre de enumeración se ocultan donde sea que la variable, miembro de datos, función o el nombre del enumerador es visible.
- Para mi sorpresa, encontré que el nombre de un objeto c ++ puede ser el mismo que el nombre de la clase. ¿Puede alguien explicarme la razón por la cual?
- Cuando declaro un objeto de la clase
a
comoa a1()
, no genera un error, pero no llama al constructor. ¿Por qué está pasando esto?
Mi código:
#include<iostream>
using namespace std;
class a
{
public:
a()
{
cout << "in a/n";
}
};
int main()
{
a a1();
a a;
}
Es válido ocultar el nombre de una clase con una variable, de hecho, si nos fijamos en el borrador de la sección 3.3.10
C ++, el párrafo 2 oculta el nombre ( énfasis mío ):
Un nombre de clase (9.1) o un nombre de enumeración (7.2) puede estar oculto por el nombre de una variable , miembro de datos, función o enumerador declarado en el mismo ámbito. Si una clase o nombre de enumeración y una variable, miembro de datos, función o enumerador se declaran en el mismo ámbito (en cualquier orden) con el mismo nombre, la clase o el nombre de enumeración se ocultan donde sea que la variable, miembro de datos, función o el nombre del enumerador es visible.
No creo que sea una buena práctica y conduciría a un código difícil de mantener. Esta línea de código en realidad está declarando una función:
a a1();
alternativamente puedes usar este pre- C ++ 11 :
a a1 ;
Inicialización uniforme o introducida en C ++ 11 :
a a1{} ;
Dando vueltas para ocultar el nombre , me sorprendió gratamente que clang
te advirtiera sobre esto con este código, independientemente de los niveles de advertencia establecidos:
int main()
{
a a;
a a2 ;
}
Recibo este mensaje:
main.cpp:12:10: note: class ''a'' is hidden by a non-type declaration of ''a'' here
a a;
^
aunque no puedo ver para obtener una advertencia similar de gcc
.
Actualizar
Al pensar en estos comentarios que hice anteriormente sobre las verrugas de la inicialización uniforme , me di cuenta de que si hubiera sospechado que a1
era del tipo correcto, podría haber usado typeid para depurar lo que estaba sucediendo. Por ejemplo este código:
std::cout << typeid(a).name() << std::endl ;
std::cout << typeid(a1).name() << std::endl ;
resultados en esta salida en Coliru ejemplo vivo :
1a
F1avE
y pasándolo a través de c++filt recibes esta salida:
a () // A function that returns type a
a // type a
Esto es lo que obtuve de tu código cuando intenté compilarlo con un clang
, creo que lo dice todo.
test.cpp:15:9: warning: empty parentheses interpreted as a function declaration
[-Wvexing-parse]
a a1();
^~
test.cpp:15:9: note: remove parentheses to declare a variable
a a1();
^~
1 warning generated.
a a1();
Es una declaración de función.
Esa es una razón importante para la creación de una inicialización uniforme en C ++ 11. Para inicializar el objeto utilizando el constructor en C ++ 11, use a a1{};
a a1();
es un tipo de devolución de declaración de función que no tiene nada que ver con el constructor que llama
aa ;
Es simple declaración funciona bien llamará el constructor