web-dev-qa-db-fra.com

Pourquoi C ++ nous permet-il d'entourer le nom de la variable entre parenthèses lors de la déclaration d'une variable?

Par exemple une déclaration comme celle-ci:

int (x) = 0;

Ou même cela:

int (((x))) = 0;

Je suis tombé sur cela parce que dans mon code, je me trouvais avoir un fragment similaire au suivant:

struct B
{
};

struct C
{
  C (B *) {}
  void f () {};
};

int main()
{
  B *y;
  C (y);
}

Évidemment, je voulais construire l'objet C qui ferait alors quelque chose d'utile dans son destructeur. Cependant, comme cela se produit, le compilateur traite C (y); comme une déclaration de variable y de type C et donc il affiche une erreur concernant y redéfinition. Ce qui est intéressant, c'est que si je l'écris en tant que C (y).f () ou quelque chose comme C (static_cast<B*> (y)), il se compilera comme prévu. La meilleure solution de contournement moderne consiste à utiliser {} Dans l'appel constructeur, bien sûr.

Donc, comme je l'ai compris après cela, il est possible de déclarer des variables comme int (x) = 0; ou même int (((x))) = 0; mais je n'ai jamais vu personne utiliser des déclarations comme celle-ci. Je suis donc intéressé-quel est le but d'une telle possibilité parce que pour l'instant je vois que cela crée seulement le cas similaire à la fameuse "analyse la plus vexante" et n'ajoute rien d'utile?

81
Predelnik

Regroupement.

À titre d'exemple particulier, considérez que vous pouvez déclarer une variable de type fonction telle que

int f(int);

Maintenant, comment déclareriez-vous un pointeur sur une telle chose?

int *f(int);

Non, ça ne marche pas! Ceci est interprété comme une fonction renvoyant int*. Vous devez ajouter des parenthèses pour le faire analyser correctement:

int (*f)(int);

La même chose avec les tableaux:

int *x[5];   // array of five int*
int (*x)[5]; // pointer to array of five int
80
Hurkyl

Il est généralement permis d'utiliser des parenthèses dans de telles déclarations car la déclaration, du point de vue syntaxique, ressemble toujours à ceci:

<front type> <specification>;

Par exemple, dans la déclaration suivante:

int* p[2];

Le "type avant" est int (pas int*) Et la "spécification" est * p[2].

La règle est que vous pouvez utiliser autant de parenthèses que nécessaire dans la partie "spécification" car elles sont parfois inévitables à lever les ambiguïtés. Par exemple:

int* p[2]; // array of 2 pointers to int; same as int (*p[2]);
int (*p)[2]; // pointer to an array of 2 ints

Le pointeur vers un tableau est un cas rare, cependant la même situation que vous avez avec un pointeur pour fonctionner:

int (*func(int)); // declares a function returning int*
int (*func)(int); // declares a pointer to function returning int

Ceci est la réponse directe à votre question. Si votre question concerne l'instruction comme C(y), alors:

  • Mettez des parenthèses autour de l'expression entière - (C(y)) Et vous obtiendrez ce que vous vouliez
  • Cette déclaration ne fait que créer un objet temporaire, qui cesse de vivre après la fin de cette instruction (j'espère que c'est ce que vous aviez l'intention de faire).
17
Ethouris