web-dev-qa-db-fra.com

Constructeur par défaut avec des crochets vides

Y a-t-il une bonne raison pour laquelle un ensemble vide de crochets (parenthèses) n'est pas valide pour appeler le constructeur par défaut en C++?

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

MyObject  object();  // error

Je semble taper "()" automatiquement à chaque fois. Y a-t-il une bonne raison pour laquelle cela n'est pas autorisé?

189
Martin Beckett

Analyse la plus vexante

Ceci est lié à ce qui est connu comme "l'analyse la plus contrariante 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.

Un autre exemple 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 de contournement 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 d'une initialisation de liste (également appelée initialisation uniforme):

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

Avec cela, il est impossible de l'interpréter comme une déclaration de fonction.

155
Constantin

Parce qu'il est traité comme la déclaration d'une fonction:

int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
100
1800 INFORMATION

La même syntaxe est utilisée pour la déclaration de fonction - par ex. la fonction object, ne prenant aucun paramètre et renvoyant MyObject

50

Parce que le compilateur pense que c'est une déclaration d'une fonction qui ne prend aucun argument et retourne une instance MyObject.

11
Fred Larson

Vous pouvez également utiliser le mode de construction le plus détaillé:

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

En C++ 0x, cela permet également de auto:

auto object1 = MyObject();
auto object2 = MyObject(object1);
8
dalle

Je suppose que le compilateur ne saurait pas si cette déclaration:

Objet MyObject ();

est un appel constructeur ou un prototype de fonction déclarant une fonction nommée objet avec le type de retour MyObject et aucun paramètre.

7
Black

Comme mentionné à plusieurs reprises, c'est une déclaration. C'est de cette façon pour la compatibilité descendante. L'un des nombreux domaines du C++ qui sont maladroits/incohérents/douloureux/faux en raison de son héritage.

5
Michael Burr

Depuis n4296 [dcl.init]:

[ Remarque:
Puisque () N'est pas autorisé par la syntaxe pour 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 renvoyant un X. La forme () est autorisée dans certains autres contextes d'initialisation (5.3.4, 5.2.3, 12.6.2).
- note de fin]

4
Andreas DM

Comme les autres l'ont dit, c'est une déclaration de fonction. Depuis C++ 11, vous pouvez utiliser l'initialisation d'accolade si vous avez besoin de voir le quelque chose vide qui vous indique explicitement qu'un constructeur par défaut est utilisé.

Jedi luke{}; //default constructor
1
Hitokage