web-dev-qa-db-fra.com

Est-ce qu'aucune parenthèse sur un constructeur sans argument n'est une norme de langage?

Je compilais un programme C++ dans Cygwin en utilisant g ++ et j'avais une classe dont le constructeur n'avait aucun argument. J'avais les lignes:

MyClass myObj();
myObj.function1();

Et en essayant de le compiler, j'ai reçu le message:

error: request for member 'function1' in 'myObj', which is of non-class type 'MyClass ()()'

Après un peu de recherche, j'ai trouvé que le correctif était de changer cette première ligne en

MyClass myObj;

Je pourrais jurer que j'ai déjà fait des déclarations de constructeur vides avec des parenthèses en C++. Est-ce probablement une limitation du compilateur que j'utilise ou la norme de langage dit-elle vraiment de ne pas utiliser de parenthèses pour un constructeur sans arguments?

51
mring

Bien que MyClass myObj(); puisse être analysé en tant que définition d'objet avec un initialiseur vide ou une déclaration de fonction, la norme de langage spécifie que l'ambiguïté est toujours résolue en faveur de la déclaration de fonction. Un initialiseur de parenthèses vide est autorisé dans d'autres contextes, par exemple dans une expression new ou la construction d'un valeur initialisée temporaire.

54
CB Bailey

C'est ce qu'on appelle le problème d'analyse le plus contrariant. Quand l'analyseur voit

MyClass myObj();

Il pense que vous déclarez une fonction appelée myObj qui n'a pas de paramètres et renvoie un MyClass.

Pour le contourner, utilisez:

MyClass myObj;
52
Peter Alexander

J'ai trouvé cela dans la norme C++ (§8.5.8):

Un objet dont l'initialiseur est un ensemble vide de parenthèses, c'est-à-dire (), doit être initialisé en valeur.

[Remarque: puisque () n'est pas autorisé par la syntaxe de l'initialiseur,

X a ();

n'est pas la déclaration d'un objet de classe X, mais la déclaration d'une fonction ne prenant aucun argument et retournant un X. La forme () est autorisée dans certains autres contextes d'initialisation (5.3.4, 5.2.3, 12.6.2). —Fin note]

19
suszterpatt

Il s'agit d'un problème assez bien connu qui ne dépend pas du compilateur. Essentiellement, ce que vous faisiez déclarait une fonction renvoyant le type MyObj. Sans surprise, vous ne pouviez pas appeler son constructeur. Voir C++ faq lite pour une bonne explication

10
Liz Albin

Pourtant, un autre succès de l'analyse la plus vexante. Voir par exemple la fonction de tri ne fonctionne pas avec l'objet fonction créé sur la pile?

4
AProgrammer
MyClass myObj();

C'est analysé comme une déclaration de fonction, la fonction s'appelle myObj, ne prend aucun argument et retourne un objet MyClass. Je n'ai jamais vu un compilateur l'accepter. D'un autre côté, MyClass* myPtr = new MyClass(); est acceptable, est-ce que cela vous a dérouté?

4
sbk

Votre ligne fait penser au compilateur que vous déclarez une fonction nommée myObj qui ne prend aucun argument et renvoie un MyClass. Cette résolution d'ambiguïté est en effet agaçante.

3
Ari

La norme ne nécessite pas de parenthèses.

int* x = new int;

est la syntaxe légale.

Dans votre cas, myclass myobj(); est un prototype de fonction. Alors que myclass myobj; Est une variable.

1
JonH