2015-04-16 9 views
75

Per esempio una dichiarazione come quella:Perché il C++ ci consente di racchiudere il nome della variabile tra parentesi quando si dichiara una variabile?

int (x) = 0; 

O anche che:

int (((x))) = 0; 

mi sono imbattuto su questo perché nel mio codice mi è capitato di avere un frammento simile a quello seguente:

Ovviamente volevo costruire l'oggetto C che poi avrebbe fatto qualcosa di utile nel suo distruttore. Tuttavia come accade il compilatore considera C (y); come una dichiarazione della variabile con tipo C e quindi stampa un errore sulla ridefinizione . La cosa interessante è che se scrivo come C (y).f() o come qualcosa come C (static_cast<B*> (y)) verrà compilato come previsto. La migliore soluzione moderna consiste nell'utilizzare {} nella chiamata del costruttore, ovviamente.

Quindi, come ho capito dopo, è possibile dichiarare variabili come int (x) = 0; o anche int (((x))) = 0; ma non ho mai visto nessuno in realtà utilizzare dichiarazioni come questa. Quindi mi interessa - qual è lo scopo di tale possibilità perché per ora vedo che crea solo il caso simile al famigerato "parse più irritante" e non aggiunge nulla di utile?

+0

Lo "scopo" della possibilità è probabilmente quello di semplificare il parser. – molbdnilo

+0

possibile duplicato di [Qual è lo scopo di una dichiarazione come int (x); o int (x) = 10;] (http://stackoverflow.com/questions/26832321/what-is-the-purpose-of-a-declaration-like-int-x-or-int-x-10) – GSerg

+1

@GSerg Divertente come il testo della mia domanda risponde alla domanda dalla seconda risposta nella tua domanda collegata, poiché fornisco l'esempio dove consentire tali dichiarazioni porta a risultati imprevisti :) – Predelnik

risposta

75

Raggruppamento.

Come esempio particolare, ritengono che è possibile dichiarare una variabile di tipo funzione come

int f(int); 

Ora, come si dovrebbe dichiarare un puntatore a una cosa del genere?

int *f(int); 

No, non funziona! Questo è interpretato come una funzione che restituisce int*. È necessario aggiungere tra parentesi per renderla analizzare nel modo giusto:

int (*f)(int); 

Lo stesso accordo con gli array:

int *x[5]; // array of five int* 
int (*x)[5]; // pointer to array of five int 
+10

E per completare la risposta: non consentire il caso particolare che il richiedente sta chiedendo avrebbe richiesto una regola del caso speciale in più. La definizione corrente di come '()' funziona in un tipo è uniforme per tutto il tipo. –

+0

Quindi il caso speciale si applica all'analisi più irritante. Questo perché la sintassi per inizializzare le variabili con gli argomenti del costruttore è stata aggiunta più tardi (in fretta credo?). – AnArrayOfFunctions

+1

@FISOCPP Bene. . sì. Il C++ è venuto dopo C. . – iheanyi

17

C'è in generale il permesso di utilizzare le parentesi in tali dichiarazioni a causa della dichiarazione, dal punto di vista sintattico si presenta sempre così:

<front type> <specification>; 

Ad esempio, nel seguente dichiarazione:

012.
int* p[2]; 

Il "tipo anteriore" è int (non int*) e la "specifica" è * p[2].

La regola è che è possibile utilizzare qualsiasi numero di parentesi secondo necessità nella parte "specifica" perché a volte sono inevitabili da disambiguare.Per esempio:

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

Il puntatore ad un array è un caso raro, ma la stessa situazione si ha con un puntatore a funzione di:

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

Questa è la risposta diretta alla sua domanda. Se la domanda riguarda l'affermazione come C(y), quindi:

  • parentesi mettere intorno l'intera espressione - (C(y)) e avrai quello che volevi
  • Questa dichiarazione non fa altro che creare un oggetto temporaneo, che cessa di vivere dopo questa istruzione termina (spero che questo è ciò che intendevi fare).
+1

Come ho detto, inizialmente stava facendo qualcosa nel distruttore, immagino che sia una cosa piuttosto standard quando si ha un certo numero di "concatenazioni" funzioni per l'impostazione di alcuni parametri e quindi facendo tutto il lavoro nel distruttore. Grazie ancora per una soluzione alternativa, suppongo che la scrittura '{}' sia la più valida dopo tutto. – Predelnik

+4

cerca di evitare di inventare la tua grammatica e utilizzare quella fornita nello standard. '' è fuorviante e sbagliato. La grammatica è '' –

+0

Hai ragione - non ho esaminato lo standard, ho appena ripetuto la regola dalla mia testa. In realtà in C++ 11 il ruolo di '' può essere giocato anche dalla parola chiave 'auto', quindi non è nemmeno sempre un tipo. – Ethouris