Constructeur par défaut avec des crochets vides
-
05-07-2019 - |
Question
Existe-t-il une bonne raison pour qu'un ensemble vide de parenthèses (parenthèses) ne soit pas valide pour appeler le constructeur par défaut en C ++?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
Il semble que je tape "" () " automatiquement à chaque fois. Y a-t-il une bonne raison pour que cela ne soit pas autorisé?
La solution
La plupart des analyses vexantes
Ceci est lié à ce que l’on appelle "l'analyse la plus frustrante de C ++". Fondamentalement, tout ce qui peut être interprété par le compilateur comme une déclaration de fonction sera interprété comme une déclaration de fonction.
Une autre instance du même problème:
std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());
v
est interprété comme une déclaration de fonction avec 2 paramètres.
La solution consiste à ajouter une autre paire de parenthèses:
std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>());
Ou, si vous disposez de C ++ 11 et de l'initialisation de liste (également appelée initialisation uniforme):
std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}};
Avec cela, il n'y a aucun moyen que cela puisse être interprété comme une déclaration de fonction.
Autres conseils
Parce que c'est le traité comme déclaration d'une fonction:
int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
La même syntaxe est utilisée pour la déclaration de fonction - par exemple. la fonction objet
, ne prenant aucun paramètre et renvoyant MyObject
Parce que le compilateur pense qu'il s'agit d'une déclaration d'une fonction qui ne prend aucun argument et renvoie une instance de MyObject.
Je suppose que le compilateur ne saurait pas si cette déclaration:
objet MyObject ();
est un appel de constructeur ou un prototype de fonction déclarant une fonction nommée objet avec le type de retour MonObjet et aucun paramètre.
Vous pouvez également utiliser la méthode de construction la plus prolixe:
MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);
En C ++ 0x, cela permet également de auto
:
auto object1 = MyObject();
auto object2 = MyObject(object1);
Comme mentionné à plusieurs reprises, il s'agit d'une déclaration. C'est ainsi pour la compatibilité ascendante. Un des nombreux domaines de C ++ qui sont maladroits / incohérents / douloureux / faux en raison de son héritage.
De n4296 [dcl.init]:
[Remarque:
Etant donné que()
n'est pas autorisé par la syntaxe de initializer ,X a ();
n'est pas la déclaration d'un objet de la classe X, mais le déclaration d’une fonction ne prenant aucun argument et renvoyant un X. Le form () est autorisé dans certains autres contextes d’initialisation (5.3.4, 5.2.3, 12.6.2).
& n ° 8212; note de fin]
Comme l'ont dit les autres, il s'agit d'une déclaration de fonction. Depuis C ++ 11, vous pouvez utiliser l'initialisation d'accolade si vous avez besoin de voir l'élément vide qui indique explicitement qu'un constructeur par défaut est utilisé.
Jedi luke{}; //default constructor