2013-08-09 11 views
6

Il soggetto è stato indirizzato principalmente qui (Where to declare/define class scope constants in C++?) e in particolare here.Definizione della costante integrale privata di una classe: nell'intestazione o nel file cpp?

Quello che vorrei per comprendere appieno, in caso di costanti integrale, c'è qualche differenza tra:

//In the header 
class A { 
private: 
static const int member = 0; //Declaration and definition 
}; 

E:

//In the header 
class A { 
private: 
static const int member; //Only declaration 
}; 

//In the cpp 
const int A::member = 0; //Definition 

(ho capito che il secondo potrebbe avere il vantaggio che se cambio il valore della costante, devo ricompilare solo un file)

Domande laterali:
Cosa succede ad esempio con un metodo inline definito nell'intestazione che accede a member? Sarà semplicemente non in linea? Cosa succederebbe se, andando a un estremo, tutti i metodi fossero definiti nel file di intestazione come metodi inline e tutte le costanti fossero definite nel file cpp?

Edit:

mia scusa: ho pensato che non era necessario, ma mi mancava il fatto che il membro è statico. La mia domanda rimane, ma ora il codice è legale.

+3

Il secondo è illegale. – chris

+0

Non penso che la seconda versione debba essere compilata. Che compilatore stai usando? – juanchopanza

+0

Quindi c'è un problema con Mingw. – juanchopanza

risposta

6

Se, come prima, la domanda è stata modificata per renderla statica, è un membro non statico, quindi può essere inizializzata solo nell'elenco di inizializzazione del costruttore o (dal 2011) nella dichiarazione del membro. Il tuo secondo esempio era mal formato.

Se è statico, allora avete bisogno di una definizione se è ODR-usato: grosso modo, se si fa tutto ciò che richiede il suo indirizzo e non solo il suo valore. Se si utilizza solo il valore, il primo esempio va bene. Ma nota che il commento è sbagliato - è solo una dichiarazione, non una definizione.

Se avete bisogno di una definizione, dipende da voi se specificate il valore nella dichiarazione o nella definizione. Specificandolo nella dichiarazione è possibile ottimizzare l'ambito di ottimizzazione, poiché il valore è sempre disponibile quando la variabile viene utilizzata. Specificandolo nella definizione si ottiene un migliore incapsulamento, richiedendo la ricompilazione di un'unità di traduzione solo se cambia.

Cosa succede ad esempio con un metodo inline definito nell'intestazione che accede al membro? Sarà semplicemente non in linea?

Non c'è alcun motivo per cui l'accesso a un oggetto dati definito in un'altra unità di traduzione dovrebbe impedire l'inclusione di una funzione.

+0

"Non c'è motivo per cui l'accesso a un oggetto dati definito in un'altra unità di traduzione dovrebbe impedire che una funzione sia in linea." Quindi, in un caso userà l'indirizzo, e in un altro caso sarà in grado di utilizzare il valore stesso al momento della compilazione, magari eseguendo alcune ottimizzazioni? – Antonio

+0

@Antonio: Sì, se il valore non è disponibile per il compilatore nel punto di utilizzo (e il compilatore non avere idonee ottimizzazioni intero programma), allora dovrà essere caricati dalla memoria in fase di esecuzione. Potrebbe essere meno ottimale di una costante codificata. –

3

Questa è la domanda di nascondere i dati. Se vuoi svelare i campi di classe interni o no. Se stai spedendo una libreria di classi e vuoi nascondere i dettagli dell'implementazione, è meglio mostrare nell'interfaccia il minor numero possibile di entità, quindi anche una dichiarazione del campo privato member è troppo.

Vorrei semplicemente dichiarare questo valore come variabile statica all'interno di un file .cpp.

2

Ci sono due punti di vista da prendere in considerazione, ovvero visibilità e indirizzamento.

nota che i due sono ortogonali, per poter effettivamente dichiarare la variabile come inizializzata e ancora definirla in un'unità di traduzione quindi ha un indirizzo effettivo in memoria.

visibilità

visibilità influisce l'uso della variabile, e ha alcuni impatti tecnici.

Per l'utilizzo nel codice modello come parametro modello non di tipo, il valore deve essere visibile nel punto di utilizzo. Inoltre, in C++ 11, potrebbe essere necessario per l'utilizzo di constexpr. In caso contrario, non è necessario che il valore sia visibile.

Tecnicamente un valore visibile può attivare le ottimizzazioni del compilatore. Ad esempio if (A::member) è banalmente falso in modo che il test possa essere eliminato. Questo è generalmente indicato come Propagazione costante. Anche se questo può sembrare un aspetto positivo, a prima vista, tuttavia, vi è un impatto profondo: tutti i client del file di intestazione dipendono potenzialmente da questo valore, pertanto qualsiasi modifica a questo valore significa che dovrebbero essere ricompilati. Se si consegna questa intestazione come parte di una libreria condivisa, ciò significa che la modifica di questo valore interrompe l'ABI.

Rivolgendosi

La regola qui è abbastanza semplice: se la variabile può essere affrontato (sia passato per puntatore o di riferimento), quindi ha bisogno di risiedere da qualche parte nella memoria. Questo richiede una definizionein uno unità di traduzione.

Problemi correlati