2012-03-28 30 views
7
//a.h 

extern int x1; 
static int x2; 
int x3; 
static const int x4; 

class A { 
    public: 
     static const int x5 = 10; 
}; 

a.h sarà incluso da più .cpp file, la mia domanda è:`static`,` extern`, `const` nel file di intestazione

1. x1 è solo una dichiarazione, non è vero? Quindi la sua definizione dovrebbe essere fatta in uno di quei file .cpp, giusto?

2. x2 è una definizione, giusto? Ero solito pensare che static int fosse anche una dichiarazione come extern int, ma mi sbagliavo. x2 sarà visibile solo in a.h?

3. saranno definiti più volte se a.h è incluso in più .cpp file, in modo da si tradurrà in fase di compilazione errore, giusto?

4. x4 è una definizione, giusto?

5.Qui in classe A, x5 è una dichiarazione, sì. Ma che dire di x4?

+0

Cosa intendi con la domanda nel punto 5? –

+0

@DavidHeffernan, intendo perché 'x5' è una dichiarazione ma' x4'? – Alcott

risposta

10

1.x1 è solo una dichiarazione, non è vero? Quindi la sua definizione dovrebbe essere fatta in uno di quei file .cpp, giusto?

corretta

2.x2 è una definizione, giusto? Pensavo che static int sia anche una dichiarazione come extern int, ma ho sbagliato. x2 sarà visibile solo in a.h?

Un diverso x2 sarà disponibile in ogni unità di traduzione che include l'intestazione.

3.x3 sarà definito più volte se a.h è incluso in più file .cpp, quindi x3 comporterà l'errore di compilazione, giusto?

Più precisamente, si verificherà un errore del linker. Il compilatore elabora ogni unità di traduzione, il linker li unisce e rileva che il simbolo è definito più volte.

4.x4 è una definizione, giusto?

Sì, è una definizione, ma come x2 ciascuna unità di traduzione avrà il proprio x4 (sia per static e poiché è const che implica collegamento interno

5.Here in classe a, X5 è una dichiarazione, sì. Ma per quanto riguarda x4?

Sì, x5 è una dichiarazione solo (con l'inizializzazione). Il mig confusione Sorgono perché la parola chiave static viene riutilizzata per significare cose diverse in diversi contesti. In x5 significa attributo della classe, mentre in x4 significa collegamento interno

Quest'ultimo caso è speciale. È l'unica dichiarazione (IIRC) in cui la dichiarazione può avere un valore e la ragione è che consente al compilatore di di utilizzare il il valore della costante in tutte le unità di traduzione che includono quell'intestazione come costante di tempo di compilazione . Se il valore doveva essere fornito con la definizione, solo una singola unità di traduzione avrebbe accesso a quel valore. La definizione di tale membro statico potrebbe essere:

const int A::x5; // no initialization here 

ed è necessario fornire uno se il membro è ODR-usato. Ora il fatto è che nella maggior parte dei casi la costante non sarà odr-used in quanto il compilatore sostituirà il valore quando viene utilizzata l'espressione A::x5. Solo quando il membro è utilizzato come lvalue è necessario alla definizione, ad esempio:

void f(const int &) {} 
int main() { 
    f(A::x5); 
} 

Poiché l'argomento per f è un riferimento, l'uso di A::x5 richiede un lvalue (nota, const-ness e lvalue/rvalue-ness sono quasi ortogonali) e ciò richiede la definizione del membro in una singola unità di traduzione nel tuo programma.

+0

Che cos'è il "collegamento interno"? – Alcott

+0

@Alcott: il simbolo non è accessibile dall'esterno dell'unità di traduzione in cui è definito. Ciò implica che se più unità di traduzione definiscono un simbolo con lo stesso nome con il collegamento interno, ciascuna unità di traduzione otterrà il proprio simbolo diverso (cioè simboli diversi anche se hanno lo stesso nome). –

4
  1. corretta

  2. È una definizione, x2 sarà 0, e ogni unità di traduzione che contiene l'intestazione avrà una propria copia di x2.

  3. Sì, ma provocherà un errore del linker, non un compilatore.

  4. Uguale a 2., ma non è possibile modificarlo.

  5. All'interno di una classe, static ha un significato diverso. È legale solo perché x5 è di tipo integrale const che è anche inizializzato.

+0

Quindi 'x2' non è una variabile globale che può essere condivisa tra più file' .cpp'? – Alcott

+0

@LuchianGrigore: in una singola unità di traduzione lo si definisce come 'const int A :: x5;' (nessuna inizializzazione consentita nella definizione). Se vuoi verificare che questa non sia una definizione, aggiungi al programma: 'void f (const int &) {} int main() {f (A :: x5); } 'e si otterrà un errore del linker (finché non si aggiunge la definizione). –

+0

@Alcott no, x2 sarà diverso per ogni file 'cpp'. –

Problemi correlati