Comment est-ce possible d’utiliser en c ++?

  1. À ma grande surprise, j’ai constaté que le nom d’un object c ++ peut être identique à celui de la classe. Quelqu’un peut-il m’expliquer la raison?
  2. Lorsque je déclare un object de classe a comme a a1() , il ne génère pas d’erreur, mais n’appelle pas le constructeur. Pourquoi cela arrive-t-il?

Mon code:

 #include using namespace std; class a { public: a() { cout << "in a\n"; } }; int main() { a a1(); aa; } 

Lorsque vous écrivez a a1(); il est en fait analysé comme une déclaration de fonction et non comme un appel au constructeur par défaut.

a a1;

appellera le constructeur par défaut correctement

Lorsque vous écrivez aa; cela fonctionne parce que le nom de la variable a la priorité sur le nom de la classe dans ce qu’on appelle masquer le nom, mais même si cela fonctionne, cela ne fera que créer de la confusion et j’éviterais de le faire.

Et pour tous ceux qui aiment les citations de normes, vous allez

Un nom de classe (9.1) ou un nom d’énumération (7.2) peut être masqué par le nom d’une variable, d’un membre de données, d’une fonction ou d’un énumérateur déclaré dans la même scope. Si un nom de classe ou d’énumération et une variable, un membre de données, une fonction ou un énumérateur sont déclarés dans la même étendue (dans n’importe quel ordre) avec le même nom, le nom de classe ou d’énumération est masqué à chaque fois que la variable, le membre de données, la fonction ou le nom de l’énumérateur est visible.

a a1(); est une déclaration de fonction.

C’est une raison importante pour la création d’initialisation uniforme dans C ++ 11. Pour initialiser l’object à l’aide du constructeur de C ++ 11, utilisez a a1{};

Il est valide de masquer le nom d’une classe avec une variable. En fait, si vous examinez le projet de norme C ++, section 3.3.10 Nom, le paragraphe 2 dit (en soulignant le mien ):

Un nom de classe (9.1) ou un nom d’énumération (7.2) peut être masqué par le nom d’une variable , d’un membre de données, d’une fonction ou d’un énumérateur déclaré dans la même scope. Si un nom de classe ou d’énumération et une variable, un membre de données, une fonction ou un énumérateur sont déclarés dans la même étendue (dans n’importe quel ordre) avec le même nom, le nom de classe ou d’énumération est masqué à chaque fois que la variable, le membre de données, la fonction ou le nom de l’énumérateur est visible.

Je ne pense pas que ce soit une bonne pratique et que cela rendrait difficile la maintenance du code. Cette ligne de code est en train de déclarer une fonction:

 a a1(); 

vous pouvez également utiliser ce pré- C ++ 11 :

 a a1 ; 

ou initialisation uniforme introduite dans C ++ 11 :

 a a1{} ; 

En revenant à la dissimulation du nom , j’ai été agréablement surpris de voir que clang vous en avertirait avec ce code, quel que soit le niveau d’avertissement défini:

 int main() { aa; a a2 ; } 

Je reçois ce message:

 main.cpp:12:10: note: class 'a' is hidden by a non-type declaration of 'a' here aa; ^ 

bien que je ne vois pas comment obtenir un avertissement similaire de la part de gcc .

Mettre à jour

En pensant aux commentaires que j’ai faits précédemment sur les verrues d’initialisation d’uniforme , je me suis rendu compte que si vous aviez soupçonné que a1 n’était pas le type correct, vous auriez pu utiliser typeid pour déboguer ce qui se passait. Par exemple ce code:

 std::cout << typeid(a).name() << std::endl ; std::cout << typeid(a1).name() << std::endl ; 

résultats dans cette sortie sur Coliru live exemple :

 1a F1avE 

et en le passant par c ++ filt vous recevez cette sortie:

 a () // A function that returns type a a // type a 

a a1(); est un type de retour de déclaration de fonction en tant a qui n’a rien à voir avec le constructeur appelant

aa ; est simple déclaration fonctionne bien appellera le constructeur

C’est ce que j’ai obtenu de votre code lorsqu’on a essayé de le comstackr avec clang , je pense que tout dit.

 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.