2012-05-30 9 views
54

Considerare una coppia di due file di origine: un file di dichiarazione dell'interfaccia (*.h o *.hpp) e il relativo file di implementazione (*.cpp).C++: Namespace - Come utilizzare correttamente i file di intestazione e origine?

Lasciate che il file *.h essere come il seguente:

namespace MyNamespace { 
    class MyClass { 
    public: 
    int foo(); 
    }; 
} 

Ho visto due diverse pratiche per l'utilizzo di spazi dei nomi nel file di origine:

*.cpp mostrando pratica # 1:

#include "MyClass.h" 
using namespace MyNamespace; 

int MyClass::foo() { ... } 

*.cpp dimostrazione pratica n. 2:

#include "MyClass.h" 
namespace MyNamespace { 

    int MyClass::foo() { ... } 

} 

La mia domanda: Ci sono delle differenze tra queste due pratiche e una è considerata migliore dell'altra?

+23

C'è anche opzione 3 : Solo noi il nome completo, ad es 'int MyNamespace :: MyClass :: foo() ...'. –

+1

Possibile duplicato: http://stackoverflow.com/questions/7789163/using-directive-best-practice – David

+0

@Dave non duplicato. Queste domande si completano a vicenda. Consiglia di aggiungere il collegamento fornito da Dave come "Leggi anche ..." a questa domanda. La mia domanda aiuterà i novizi a scegliere lo stile corretto. – DaddyM

risposta

42

Dal punto di vista la leggibilità del codice, è probabilmente meglio a mio parere per utilizzare il metodo # 2 per questa ragione:

si può essere using più spazi dei nomi alla volta, e qualsiasi oggetto o una funzione scritto sotto quella linea può appartenere a uno di questi spazi dei nomi (con esclusione dei conflitti di denominazione). Avvolgendo l'intero file in un blocco namespace è più esplicito, e permette di dichiarare nuove funzioni e le variabili che appartengono a tale spazio dei nomi all'interno del file cpp nonché

+0

Grazie. Molto chiaro. Aspetterò un po 'per altre risposte. – DaddyM

+0

La domanda che Dave ha collegato nel suo commento alla tua domanda delinea anche alcuni punti chiave delle differenze (se ce ne sono) tra i due metodi che stai guardando –

+0

Ragazzi, non so davvero quale sia la risposta da selezionare. Hanno intersezioni e si completano a vicenda. – DaddyM

36

Il più chiaro è l'opzione non ha mostrato:

int MyNamespace::MyClass::foo() 
{ 
    // ... 
} 

È anche molto prolisso; troppo per la maggior parte delle persone. Dal using namespace è un recepe per conflitti di nome, almeno nella mia esperienza, e dovrebbe essere evitato tranne in ambiti e posti molto limitati, I generalmente uso il n.

+2

Grazie molto chiaro. Insieme abbiamo creato una buona pagina di FAQ per gli utenti dei domini. :) – DaddyM

+0

Ragazzi, non so davvero quale sia la risposta da selezionare. Hanno intersezioni e si completano a vicenda. – DaddyM

4

Ci sono delle differenze tra queste due pratiche

Sì. # 1 e # 2 sono esempi rispettivamente di using-directive e namespace definition. In questo caso sono effettivamente uguali ma hanno altre conseguenze. Per esempio, se si introduce un nuovo identificativo a fianco MyClass::foo, avrà una portata diversa:

# 1:

using namespace MyNamespace; 
int x; // defines ::x 

# 2:

namespace MyNamespace { 
    int x; // defines MyNamespace::x 
} 

è quello considerato migliore rispetto l'altro?

# 1 Pro: un po 'più conciso; più difficile introdurre involontariamente qualcosa in MyNamespace involontariamente. Contro: potrebbe inserire gli identificatori esistenti involontariamente.

# 2 Pro: più chiaro che le definizioni di identificatori esistenti e dichiarazioni di nuovi identificatori appartengono entrambi a MyNamespace. Contro: più facile introdurre involontariamente identificatori a MyNamespace.

Una critica sia del numero 1 sia del numero 2 è che si riferiscono a un intero spazio dei nomi quando probabilmente si interessa solo della definizione dei membri di MyNamespace::MyClass. Questo è pesante e comunica male l'intento.

Una possibile alternativa a # 1 è un using-declaration che include solo l'identificatore che ti interessa:

#include "MyClass.h" 
using MyNamespace::MyClass; 

int MyClass::foo() { ... } 
2

Vorrei anche aggiungere che se si decide causa di qualche ragione per implementare un modello specializzazione in un file cpp e fare affidamento solo su using namespace vi imbatterete nella seguente problema:

// .h file 
namespace someNameSpace 
{ 
    template<typename T> 
    class Demo 
    { 
     void foo(); 
    }; 
} 

// .cpp file 
using namespace someNameSpace; 

template<typename T> 
void Demo<T>::foo(){} 

// this will produce 
// error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive] 
template<> 
void Demo<int>::foo(){} 

Altrimenti se si applica # 2 metodo questo andrà bene.

0

vorrei aggiungere un altro modo, utilizzando dichiarazione using:

#include "MyClass.h" 
using MyNamespace::MyClass; 

int MyClass::foo() { ... } 

In questo modo si salva da digitando il nome dello spazio dei nomi molte volte se la classe ha molte funzioni

Problemi correlati