2010-10-08 8 views
7

Ho letto articoli su domini senza nome per tutto il giorno, la maggior parte degli articoli ha spiegato quando è necessario utilizzare spazi dei nomi senza nome sulla parola chiave statica. Ma mi rimane ancora una grande domanda quando è appropriato usare l'elettricità statica? Dopotutto non è completamente deprecato, cosa dire dei file header con funzioni statiche se li metto ora in namespace senza nome?Quando è opportuno utilizzare statici (su namespace senza nome) in C++?

#ifndef HEADER_H 
#define HEADER_H 

static int func() { 
    ... 
} 

// versus: 

namespace { 
    int func() { 
    ... 
    } 
}; 

#endif // HEADER_H 

O per le funzioni membro statiche?

Saluti

+7

Sembra controproducente inserire file di intestazione statici (o non denominati) nei file di intestazione. Se sono statici, perché non si trovano solo nel file sorgente? –

risposta

3

Non v'è alcun vantaggio di statica del perimetro dello spazio dei nomi sopra namespace senza nome, che io sappia. Utilizzare gli spazi dei nomi senza nome, come nell'esempio sopra. In realtà nell'esempio sopra non riesco a capire perché sia ​​necessario lo spazio dei nomi statico o non denominato. Forse in linea? E le funzioni dei membri statici non hanno nulla a che fare con lo statico nell'ambito dello spazio dei nomi. Le funzioni membro statico (e membri non funzionanti) sono ancora valide.

+0

Nell'esempio è necessaria la statica per evitare che la funzione abbia un collegamento esterno. Poiché verrà implementato in ogni modulo che utilizza l'intestazione, il linker potrebbe obiettare se la parola chiave static non è presente. –

+0

@Alexander: Beh, in linea consentirà più definizioni della funzione. E secondo me è un'alternativa superiore. Tuttavia, se "INTERNAL LINKAGE" è esattamente ciò che è necessario, allora lo spazio dei nomi senza nome è molto meglio, almeno perché non è deprecato. –

+4

'inline' consente più definizioni * identiche * della funzione. 'static' consente molteplici definizioni diverse, dato che ogni unità di traduzione ha una propria funzione con collegamento interno, a cui capita semplicemente di fare riferimento con lo stesso nome. Quindi, se c'è qualcosa nella definizione di 'func' che dipende da alcuni #defines (come ad esempio' assert'), e vuoi che sia legale combinare diverse TU che includono l'intestazione con valori diversi nel #define, quindi avresti bisogno di 'static' o di uno spazio dei nomi senza nome. 'inline' non funzionerà, ufficialmente, anche se in pratica potrebbe funzionare. –

5

L'esatta formulazione della norma è:

L'utilizzo della parola chiave static è deprecato quando si dichiara oggetti in ambito spazio dei nomi.

funzioni in un file di intestazione deve essere inline piuttosto che static o in uno spazio dei nomi senza nome. inline significa che si finirà con al massimo una sola copia della funzione nel programma, mentre gli altri metodi forniranno una copia separata da ciascun file che include l'intestazione. Oltre a gonfiare, questo potrebbe dare un comportamento errato se la funzione contiene dati statici di funzione. (EDIT: a meno che la funzione debba avere definizioni diverse in unità di compilazione diverse, forse a causa di diverse macro di preprocessore definite prima di includere il file di intestazione. In tal caso, l'approccio migliore non è includerlo affatto, ma piuttosto per seppellirlo in una tomba non segnata con un paletto attraverso il suo cuore empio.)

Gli oggetti dati, a parte le costanti, di solito non dovrebbero essere definiti nei file di intestazione, solo dichiarati extern.

Le funzioni membro statico sono un diverso tipo di pesce e devi utilizzare static perché non c'è altro modo per dichiararle. Quell'uso non è deprecato, poiché non è nello scope namespace.

UPDATE: C++ 11 ha rimosso il deprecation, quindi non c'è più alcun motivo particolare per preferire namespace senza nome su static. Ma non dovresti ancora usare un file di intestazione se non stai facendo qualcosa di strano.

+0

"Gli oggetti dati non dovrebbero essere definiti nei file di intestazione, solo dichiarati extern se hanno bisogno di un collegamento esterno." Questo è impreciso. "L'oggetto dati", come li chiami, ha un collegamento esterno per impostazione predefinita, a meno che non siano const. Quindi extern è necessario per rendere la loro dichiarazione solo una dichiarazione e non una definizione, che è l'impostazione predefinita. Tuttavia, se sono presenti sia extern sia un inizializzatore, è una definizione. –

+0

Spesso gli oggetti dati devono essere definiti nei file di intestazione. Ciò include le costanti (che sono oggetti). Immagino sia un buon consiglio per i novizi di C++ di evitare di definire costanti (membri di classi statiche) di tipi non-integrali nei file di intestazione. I programmatori più esperti possono farlo utilizzando, ad es. il trucco delle costelle basato sui modelli. Un altro tale trucco è una funzione che restituisce un riferimento a una costante statica locale. –

+0

@Armen, @Alf: sì, il mio consiglio sugli oggetti dati era un po 'semplicistico. Lo riformulerò. –

3

In un file di intestazione, in genere non è necessario specificare il collegamento interno o utilizzare uno spazio dei nomi anonimo.

In un file di implementazione compilato separatamente è possibile utilizzare static o uno spazio dei nomi anonimo per evitare collisioni di nomi a livello di collegamento o codice client che si basa sui dettagli di implementazione. Un namespace anonimo ti consente di avere un collegamento esterno, richiesto per i parametri del modello, e supporta anche le definizioni di classe. Ma alla fine è solo una questione di praticità e preferenza personale, caso per caso.

static per una funzione membro non ha nulla a che fare con le specifiche del collegamento. Una funzione membro static ha comunque un collegamento esterno.

0

static può essere preferibile se si utilizzano alcuni strumenti. Si comporta anche un po 'meglio con la funzionalità di rientro automatico nella maggior parte degli editor di testo. È un po 'triste, quando devi evitare di usare qualcosa di utile perché non funziona con strumenti che dovrebbero davvero supportarlo, ma ti prometto che lo supererai.

Una questione di esempio che dà qualche accenno di dolore potenziale nel reparto di debug:

Viewing namespaced global variables in Visual Studio debugger?

Probabilmente non c'è bisogno di guardare molto difficile da trovare più problemi, ma i problemi del debugger sono stati sufficienti a farmi rinunciare completamente ai namespace, nella misura massima possibile, quindi non ho mai guardato oltre.

La mia raccomandazione personale è che per il codice che sarà in giro per meno di sempre, uno potrebbe anche andare con static. Fa effettivamente la stessa cosa di uno spazio dei nomi senza nome, ma, con una media su tutti gli strumenti, è meglio supportato. In teoria, un giorno sparirà completamente, ma sono felice di ammettere pubblicamente che sono sicuro che quel giorno non si realizzerà mai. E nel frattempo, ti stai risparmiando un po 'di dolore.

Problemi correlati