2009-09-04 18 views
9

Dai un'occhiata qui: Nel seguente codice, quale sarebbe il tipo di b?domanda di trucco relativa alla sintassi della dichiarazione in C++

struct A { 
    A (int i) {} 
}; 

struct B { 
    B (A a) {} 
}; 

int main() { 
    int i = 1; 
    B b(A(i)); // what would be the type of b 
    return 0; 
} 

sarò grato se qualcuno potesse spiegarmi bene il motivo per cui esisterebbe tali sintassi :)

Grazie.

risposta

7

Una delle verruche di C (e C++ la eredita (e lo rende peggiore)) è che non esiste una sintassi speciale per l'introduzione di una dichiarazione. Ciò significa che le dichiarazioni spesso assomigliano al codice eseguibile. Un altro esempio:

A * a; 

È questo moltiplicando A di a, o sta dichiarando qualcosa? Per dare un senso a questa linea devi sapere che A è il nome di un tipo.

La regola di base in C++ è che se qualcosa può essere analizzato come una dichiarazione, lo è. In questo caso porta a un risultato strano e sorprendente. Le dichiarazioni delle funzioni assomigliano molto alle chiamate di funzione, in particolare la (dopo la A può essere pensata in un paio di modi.

È possibile aggirare questo in questo esempio con parentesi aggiuntiva che rimuove la capacità del compilatore di analizzare codice come una dichiarazione.

B b((A(i))); 

In C questo non è ambiguo, perché non c'è uno stile funzione della chiamata al costruttore perché non ci sono i costruttori. una è il nome di un tipo, o è il nome di una funzione Non può essere entrambi.

+2

io credo che si potrebbe anche do: B b = B (A (i)); – Bill

+0

Sì, funzionerebbe anche, è più facile da capire e meno brutto. :-) – Omnifarious

+2

... ma significa una cosa diversa - 'B b = B (...)' richiede 'B' di avere un costruttore di copia (anche se il compilatore può ottimizzare la chiamata ad esso, è ancora necessario per controllare), mentre 'B b (...)' non lo richiede. –

7

È una dichiarazione di funzione locale in base allo standard C++ 8.2/1. Si potrebbe utilizzare forma implicita di costruttore per evitare questo o il seguente:

B b(A(i)); // is equal to B b(A i); 

// --- 

// to declare variable of type B write: 
B b = A(i); 
// explicit form if you want: 
B b(static_cast<A>(A(i))); 
// or 
B b((A)i); 

C++ standard 8.2/1:

L'ambiguità derivante dalla somiglianza tra un cast di tipo funzione e una dichiarazione di cui al 6.8 può anche verificarsi nel contesto di una dichiarazione. In tale contesto, la scelta è tra una dichiarazione di funzione con un insieme ridondante di parentesi attorno al nome di un parametro e una dichiarazione di oggetto con un cast di stile convertito come inizializzatore. Proprio come per le ambiguità di cui al 6.8, la risoluzione è di prendere in considerazione qualsiasi struttura di con- che potrebbe essere una dichiarazione di dichiarazione.

5
B b(A(i)); 

è equivalente a

B b(A i); 

- le parentesi attorno al nome argomento sono opzionali -, che equivale a

B b(A); 

- il nome del parametro è facoltativo in dichiarazioni di funzioni. Quindi è una dichiarazione di funzione.

In genere si esegue in con

X x(); 

- non predefinito costruttore come previsto -, ma ci sono casi più complicati quando si utilizza provvisori tutta la strada, ad esempio

vector<int> v(istream_iterator<int>(cin), istream_iterator<int>()); 
+0

Inaspettatamente, è diventato un buon argomento contro l'uso di namespace :) :) –

+0

Sfortunatamente va più in profondità. Se cin fosse stato std :: cin allora GCC determinerà che questa linea costruisce effettivamente un oggetto vettoriale, mentre VC++ (2005) si lamenta che std :: cin non può apparire come nome parametro. – UncleBens

+0

@UncleBens, Sfortunatamente GCC ha torto e VC++ è corretto. Vedi il mio rapporto sui difetti a clang: http://llvm.org/bugs/show_bug.cgi?id=4594 –

Problemi correlati